Loading core/java/android/view/WindowManager.java +37 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.List; import java.util.Objects; Loading Loading @@ -2895,6 +2896,18 @@ public interface WindowManager extends ViewManager { private boolean mFitInsetsIgnoringVisibility = false; /** * {@link InsetsState.InternalInsetsType}s to be applied to the window * If {@link #type} has the predefined insets (like {@link #TYPE_STATUS_BAR} or * {@link #TYPE_NAVIGATION_BAR}), this field will be ignored. * * <p>Note: provide only one inset corresponding to the window type (like * {@link InsetsState.InternalInsetsType#ITYPE_STATUS_BAR} or * {@link InsetsState.InternalInsetsType#ITYPE_NAVIGATION_BAR})</p> * @hide */ public @InsetsState.InternalInsetsType int[] providesInsetsTypes; /** * Specifies types of insets that this window should avoid overlapping during layout. * Loading Loading @@ -3116,6 +3129,12 @@ public interface WindowManager extends ViewManager { out.writeInt(mFitInsetsSides); out.writeBoolean(mFitInsetsIgnoringVisibility); out.writeBoolean(preferMinimalPostProcessing); if (providesInsetsTypes != null) { out.writeInt(providesInsetsTypes.length); out.writeIntArray(providesInsetsTypes); } else { out.writeInt(0); } } public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR Loading Loading @@ -3177,6 +3196,11 @@ public interface WindowManager extends ViewManager { mFitInsetsSides = in.readInt(); mFitInsetsIgnoringVisibility = in.readBoolean(); preferMinimalPostProcessing = in.readBoolean(); int insetsTypesLength = in.readInt(); if (insetsTypesLength > 0) { providesInsetsTypes = new int[insetsTypesLength]; in.readIntArray(providesInsetsTypes); } } @SuppressWarnings({"PointlessBitwiseExpression"}) Loading Loading @@ -3437,6 +3461,11 @@ public interface WindowManager extends ViewManager { changes |= LAYOUT_CHANGED; } if (!Arrays.equals(providesInsetsTypes, o.providesInsetsTypes)) { providesInsetsTypes = o.providesInsetsTypes; changes |= LAYOUT_CHANGED; } return changes; } Loading Loading @@ -3609,6 +3638,14 @@ public interface WindowManager extends ViewManager { sb.append(System.lineSeparator()); sb.append(prefix).append(" fitIgnoreVis"); } if (providesInsetsTypes != null) { sb.append(System.lineSeparator()); sb.append(prefix).append(" insetsTypes="); for (int i = 0; i < providesInsetsTypes.length; ++i) { if (i > 0) sb.append(' '); sb.append(InsetsState.typeToString(providesInsetsTypes[i])); } } sb.append('}'); return sb.toString(); Loading services/core/java/com/android/server/wm/DisplayPolicy.java +30 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.view.Display.TYPE_INTERNAL; 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_IME; import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_LEFT_GESTURES; Loading Loading @@ -1024,6 +1025,13 @@ public class DisplayPolicy { case TYPE_STATUS_BAR_PANEL: return WindowManagerGlobal.ADD_INVALID_TYPE; } if (attrs.providesInsetsTypes != null) { mContext.enforcePermission( android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid, "DisplayPolicy"); enforceSingleInsetsTypeCorrespondingToWindowType(attrs.providesInsetsTypes); } return ADD_OKAY; } Loading Loading @@ -1110,6 +1118,28 @@ public class DisplayPolicy { }); if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar); break; default: if (attrs.providesInsetsTypes != null) { for (int insetsType : attrs.providesInsetsTypes) { mDisplayContent.setInsetProvider(insetsType, win, null); } } break; } } private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) { int count = 0; for (int insetsType : insetsTypes) { switch (insetsType) { case ITYPE_NAVIGATION_BAR: case ITYPE_STATUS_BAR: case ITYPE_CAPTION_BAR: if (++count > 1) { throw new IllegalArgumentException( "Multiple InsetsTypes corresponding to Window type"); } } } } Loading services/tests/wmtests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ android_test { "mockito-target-extended-minus-junit4", "platform-test-annotations", "servicestests-utils", "testng", "truth-prebuilt", "testables", "ub-uiautomator", Loading services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +57 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ 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_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.ITYPE_TOP_GESTURES; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; Loading @@ -42,13 +45,17 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; import static org.testng.Assert.expectThrows; import android.app.WindowConfiguration; import android.graphics.Insets; Loading Loading @@ -153,6 +160,56 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { assertEquals(0, mWindow.mAttrs.subtreeSystemUiVisibility); } @Test public void addingWindow_withInsetsTypes() { WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel"); win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_TOP_GESTURES}; win.getFrameLw().set(0, 0, 500, 100); addWindow(win); InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.onPostLayout(); InsetsSourceProvider statusBarProvider = controller.getSourceProvider(ITYPE_STATUS_BAR); assertEquals(new Rect(0, 0, 500, 100), statusBarProvider.getSource().getFrame()); assertEquals(Insets.of(0, 100, 0, 0), statusBarProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */)); InsetsSourceProvider topGesturesProvider = controller.getSourceProvider(ITYPE_TOP_GESTURES); assertEquals(new Rect(0, 0, 500, 100), topGesturesProvider.getSource().getFrame()); assertEquals(Insets.of(0, 100, 0, 0), topGesturesProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */)); InsetsSourceProvider navigationBarProvider = controller.getSourceProvider( ITYPE_NAVIGATION_BAR); assertNotEquals(new Rect(0, 0, 500, 100), navigationBarProvider.getSource().getFrame()); } @Test public void addingWindow_ignoresInsetsTypes_InWindowTypeWithPredefinedInsets() { mDisplayPolicy.removeWindowLw(mStatusBarWindow); // Removes the existing one. WindowState win = createWindow(null, TYPE_STATUS_BAR, "StatusBar"); win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR}; win.getFrameLw().set(0, 0, 500, 100); addWindow(win); mDisplayContent.getInsetsStateController().onPostLayout(); InsetsSourceProvider provider = mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR); assertNotEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame()); } @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}; expectThrows(IllegalArgumentException.class, () -> addWindow(win)); } @Test public void layoutWindowLw_fitStatusBars() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); Loading Loading
core/java/android/view/WindowManager.java +37 −0 Original line number Diff line number Diff line Loading @@ -89,6 +89,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.List; import java.util.Objects; Loading Loading @@ -2895,6 +2896,18 @@ public interface WindowManager extends ViewManager { private boolean mFitInsetsIgnoringVisibility = false; /** * {@link InsetsState.InternalInsetsType}s to be applied to the window * If {@link #type} has the predefined insets (like {@link #TYPE_STATUS_BAR} or * {@link #TYPE_NAVIGATION_BAR}), this field will be ignored. * * <p>Note: provide only one inset corresponding to the window type (like * {@link InsetsState.InternalInsetsType#ITYPE_STATUS_BAR} or * {@link InsetsState.InternalInsetsType#ITYPE_NAVIGATION_BAR})</p> * @hide */ public @InsetsState.InternalInsetsType int[] providesInsetsTypes; /** * Specifies types of insets that this window should avoid overlapping during layout. * Loading Loading @@ -3116,6 +3129,12 @@ public interface WindowManager extends ViewManager { out.writeInt(mFitInsetsSides); out.writeBoolean(mFitInsetsIgnoringVisibility); out.writeBoolean(preferMinimalPostProcessing); if (providesInsetsTypes != null) { out.writeInt(providesInsetsTypes.length); out.writeIntArray(providesInsetsTypes); } else { out.writeInt(0); } } public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR Loading Loading @@ -3177,6 +3196,11 @@ public interface WindowManager extends ViewManager { mFitInsetsSides = in.readInt(); mFitInsetsIgnoringVisibility = in.readBoolean(); preferMinimalPostProcessing = in.readBoolean(); int insetsTypesLength = in.readInt(); if (insetsTypesLength > 0) { providesInsetsTypes = new int[insetsTypesLength]; in.readIntArray(providesInsetsTypes); } } @SuppressWarnings({"PointlessBitwiseExpression"}) Loading Loading @@ -3437,6 +3461,11 @@ public interface WindowManager extends ViewManager { changes |= LAYOUT_CHANGED; } if (!Arrays.equals(providesInsetsTypes, o.providesInsetsTypes)) { providesInsetsTypes = o.providesInsetsTypes; changes |= LAYOUT_CHANGED; } return changes; } Loading Loading @@ -3609,6 +3638,14 @@ public interface WindowManager extends ViewManager { sb.append(System.lineSeparator()); sb.append(prefix).append(" fitIgnoreVis"); } if (providesInsetsTypes != null) { sb.append(System.lineSeparator()); sb.append(prefix).append(" insetsTypes="); for (int i = 0; i < providesInsetsTypes.length; ++i) { if (i > 0) sb.append(' '); sb.append(InsetsState.typeToString(providesInsetsTypes[i])); } } sb.append('}'); return sb.toString(); Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +30 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.view.Display.TYPE_INTERNAL; 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_IME; import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_LEFT_GESTURES; Loading Loading @@ -1024,6 +1025,13 @@ public class DisplayPolicy { case TYPE_STATUS_BAR_PANEL: return WindowManagerGlobal.ADD_INVALID_TYPE; } if (attrs.providesInsetsTypes != null) { mContext.enforcePermission( android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid, "DisplayPolicy"); enforceSingleInsetsTypeCorrespondingToWindowType(attrs.providesInsetsTypes); } return ADD_OKAY; } Loading Loading @@ -1110,6 +1118,28 @@ public class DisplayPolicy { }); if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar); break; default: if (attrs.providesInsetsTypes != null) { for (int insetsType : attrs.providesInsetsTypes) { mDisplayContent.setInsetProvider(insetsType, win, null); } } break; } } private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) { int count = 0; for (int insetsType : insetsTypes) { switch (insetsType) { case ITYPE_NAVIGATION_BAR: case ITYPE_STATUS_BAR: case ITYPE_CAPTION_BAR: if (++count > 1) { throw new IllegalArgumentException( "Multiple InsetsTypes corresponding to Window type"); } } } } Loading
services/tests/wmtests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ android_test { "mockito-target-extended-minus-junit4", "platform-test-annotations", "servicestests-utils", "testng", "truth-prebuilt", "testables", "ub-uiautomator", Loading
services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +57 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ 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_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.ITYPE_TOP_GESTURES; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; Loading @@ -42,13 +45,17 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; import static org.testng.Assert.expectThrows; import android.app.WindowConfiguration; import android.graphics.Insets; Loading Loading @@ -153,6 +160,56 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { assertEquals(0, mWindow.mAttrs.subtreeSystemUiVisibility); } @Test public void addingWindow_withInsetsTypes() { WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel"); win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_TOP_GESTURES}; win.getFrameLw().set(0, 0, 500, 100); addWindow(win); InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.onPostLayout(); InsetsSourceProvider statusBarProvider = controller.getSourceProvider(ITYPE_STATUS_BAR); assertEquals(new Rect(0, 0, 500, 100), statusBarProvider.getSource().getFrame()); assertEquals(Insets.of(0, 100, 0, 0), statusBarProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */)); InsetsSourceProvider topGesturesProvider = controller.getSourceProvider(ITYPE_TOP_GESTURES); assertEquals(new Rect(0, 0, 500, 100), topGesturesProvider.getSource().getFrame()); assertEquals(Insets.of(0, 100, 0, 0), topGesturesProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */)); InsetsSourceProvider navigationBarProvider = controller.getSourceProvider( ITYPE_NAVIGATION_BAR); assertNotEquals(new Rect(0, 0, 500, 100), navigationBarProvider.getSource().getFrame()); } @Test public void addingWindow_ignoresInsetsTypes_InWindowTypeWithPredefinedInsets() { mDisplayPolicy.removeWindowLw(mStatusBarWindow); // Removes the existing one. WindowState win = createWindow(null, TYPE_STATUS_BAR, "StatusBar"); win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR}; win.getFrameLw().set(0, 0, 500, 100); addWindow(win); mDisplayContent.getInsetsStateController().onPostLayout(); InsetsSourceProvider provider = mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR); assertNotEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame()); } @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}; expectThrows(IllegalArgumentException.class, () -> addWindow(win)); } @Test public void layoutWindowLw_fitStatusBars() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL); Loading