diff options
5 files changed, 164 insertions, 18 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index dad767142ba1..e731323845d3 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -3687,6 +3687,8 @@ public interface WindowManager extends ViewManager { return "always"; case LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER: return "never"; + case LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES: + return "shortEdges"; default: return "unknown(" + mode + ")"; } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index c78707a2204e..089e529746a0 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -57,8 +57,8 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATIO import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT; -import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; @@ -855,7 +855,7 @@ public class DisplayPolicy { case TYPE_WALLPAPER: // Dreams and wallpapers don't have an app window token and can thus not be // letterboxed. Hence always let them extend under the cutout. - attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; break; case TYPE_NOTIFICATION_SHADE: // If the Keyguard is in a hidden state (occluded by another window), we force to @@ -2298,15 +2298,24 @@ public class DisplayPolicy { // cropped / shifted to the displayFrame in WindowState. final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen && type != TYPE_BASE_APPLICATION; - // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in // the cutout safe zone. - if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT - || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER) { + if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) { final Rect displayCutoutSafeExceptMaybeBars = sTmpDisplayCutoutSafeExceptMaybeBarsRect; displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe); + if (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) { + if (displayFrames.mDisplayWidth < displayFrames.mDisplayHeight) { + displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE; + displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE; + } else { + displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE; + displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE; + } + } + if (layoutInScreen && layoutInsetDecor && !requestedFullscreen - && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) { + && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT + || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) { // At the top we have the status bar, so apps that are // LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN // already expect that there's an inset there and we don't need to exclude @@ -2314,7 +2323,8 @@ public class DisplayPolicy { displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE; } if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation - && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) { + && (cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT + || cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)) { // Same for the navigation bar. switch (mNavigationBarPosition) { case NAV_BAR_BOTTOM: diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java index f754c5956cd9..39cd76aeef9e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java @@ -174,6 +174,6 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { } private static DisplayInfo displayInfoForRotation(int rotation, boolean withDisplayCutout) { - return displayInfoAndCutoutForRotation(rotation, withDisplayCutout).first; + return displayInfoAndCutoutForRotation(rotation, withDisplayCutout, false).first; } } 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 e6291a4c34ac..c19312debce3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -34,6 +34,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; @@ -91,6 +92,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { private WindowState mWindow; private int mRotation = ROTATION_0; private boolean mHasDisplayCutout; + private boolean mIsLongEdgeDisplayCutout; private static final int DECOR_WINDOW_INSET = 50; @Before @@ -124,6 +126,12 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { updateDisplayFrames(); } + public void addLongEdgeDisplayCutout() { + mHasDisplayCutout = true; + mIsLongEdgeDisplayCutout = true; + updateDisplayFrames(); + } + private void updateDisplayFrames() { mFrames = createDisplayFrames(); mDisplayContent.mDisplayFrames = mFrames; @@ -131,7 +139,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { private DisplayFrames createDisplayFrames() { final Pair<DisplayInfo, WmDisplayCutout> info = displayInfoAndCutoutForRotation(mRotation, - mHasDisplayCutout); + mHasDisplayCutout, mIsLongEdgeDisplayCutout); return new DisplayFrames(mDisplayContent.getDisplayId(), info.first, info.second); } @@ -376,6 +384,46 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { } @Test + public void layoutWindowLw_withDisplayCutout_shortEdges() { + addDisplayCutout(); + + mWindow.mAttrs.flags = + FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + mWindow.mAttrs.setFitInsetsTypes(0 /* types */); + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getContentFrameLw(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); + } + + @Test + public void layoutWindowLw_withDisplayCutout_always() { + addDisplayCutout(); + + mWindow.mAttrs.flags = + FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + mWindow.mAttrs.setFitInsetsTypes(0 /* types */); + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getContentFrameLw(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); + } + + @Test public void layoutWindowLw_withDisplayCutout_layoutFullscreen() { addDisplayCutout(); @@ -551,6 +599,88 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { } @Test + public void layoutWindowLw_withLongEdgeDisplayCutout() { + addLongEdgeDisplayCutout(); + + mWindow.mAttrs.flags = + FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getContentFrameLw(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, + NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + } + + @Test + public void layoutWindowLw_withLongEdgeDisplayCutout_never() { + addLongEdgeDisplayCutout(); + + mWindow.mAttrs.flags = + FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, 0, + NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getContentFrameLw(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, + NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + } + + @Test + public void layoutWindowLw_withLongEdgeDisplayCutout_shortEdges() { + addLongEdgeDisplayCutout(); + + mWindow.mAttrs.flags = + FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + mWindow.mAttrs.setFitInsetsTypes(0 /* types */); + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getContentFrameLw(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, + NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); + } + + @Test + public void layoutWindowLw_withLongEdgeDisplayCutout_always() { + addLongEdgeDisplayCutout(); + + mWindow.mAttrs.flags = + FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + mWindow.mAttrs.setFitInsetsTypes(0 /* types */); + mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + addWindow(mWindow); + + mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); + + assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getStableFrameLw(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getContentFrameLw(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, + NAV_BAR_HEIGHT); + assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); + assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0); + } + + @Test public void layoutWindowLw_withForwardInset_SoftInputAdjustResize() { assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_NONE); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java index d0b335082ef5..2a20c2e959cc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java @@ -111,7 +111,7 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { } static Pair<DisplayInfo, WmDisplayCutout> displayInfoAndCutoutForRotation(int rotation, - boolean withDisplayCutout) { + boolean withDisplayCutout, boolean isLongEdgeCutout) { final DisplayInfo info = new DisplayInfo(); WmDisplayCutout cutout = null; @@ -121,7 +121,7 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { info.rotation = rotation; if (withDisplayCutout) { cutout = WmDisplayCutout.computeSafeInsets( - displayCutoutForRotation(rotation), info.logicalWidth, + displayCutoutForRotation(rotation, isLongEdgeCutout), info.logicalWidth, info.logicalHeight); info.displayCutout = cutout.getDisplayCutout(); } else { @@ -130,9 +130,13 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { return Pair.create(info, cutout); } - private static DisplayCutout displayCutoutForRotation(int rotation) { - final RectF rectF = - new RectF(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT); + private static DisplayCutout displayCutoutForRotation(int rotation, boolean isLongEdgeCutout) { + RectF rectF = new RectF(); + if (isLongEdgeCutout) { + rectF.set(0, DISPLAY_HEIGHT / 4, DISPLAY_CUTOUT_HEIGHT, DISPLAY_HEIGHT * 3 / 4); + } else { + rectF.set(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT); + } final Matrix m = new Matrix(); transformPhysicalToLogicalCoordinates(rotation, DISPLAY_WIDTH, DISPLAY_HEIGHT, m); @@ -141,16 +145,16 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { int pos = -1; switch (rotation) { case ROTATION_0: - pos = BOUNDS_POSITION_TOP; + pos = isLongEdgeCutout ? BOUNDS_POSITION_LEFT : BOUNDS_POSITION_TOP; break; case ROTATION_90: - pos = BOUNDS_POSITION_LEFT; + pos = isLongEdgeCutout ? BOUNDS_POSITION_BOTTOM : BOUNDS_POSITION_LEFT; break; case ROTATION_180: - pos = BOUNDS_POSITION_BOTTOM; + pos = isLongEdgeCutout ? BOUNDS_POSITION_RIGHT : BOUNDS_POSITION_BOTTOM; break; case ROTATION_270: - pos = BOUNDS_POSITION_RIGHT; + pos = isLongEdgeCutout ? BOUNDS_POSITION_TOP : BOUNDS_POSITION_RIGHT; break; } |