OSDN Git Service

DisplayCutout: account for cutout in appWidth/appHeight etc.
authorAdrian Roos <roosa@google.com>
Mon, 19 Feb 2018 17:06:36 +0000 (18:06 +0100)
committerAdrian Roos <roosa@google.com>
Tue, 20 Feb 2018 17:05:59 +0000 (17:05 +0000)
Makes sure to take into account the area blocked by the cutout when
calculating the nonDecor / config / stable insets, widths and heights.

Fixes: 72995358
Fixes: 72444324
Test: atest PhoneWindowManagerInsetsTest
Test: go/wm-smoke
Test: Enter splitscreen, verify that both windows are same size

Change-Id: Iff58235b5bdfd0d49df259a91b05e54e3864f41c

services/core/java/com/android/server/policy/PhoneWindowManager.java
services/core/java/com/android/server/policy/WindowManagerPolicy.java
services/core/java/com/android/server/wm/DisplayContent.java
services/core/java/com/android/server/wm/DockedStackDividerController.java
services/core/java/com/android/server/wm/PinnedStackController.java
services/core/java/com/android/server/wm/StackWindowController.java
services/core/java/com/android/server/wm/TaskStack.java
services/core/java/com/android/server/wm/WindowManagerService.java
services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java [new file with mode: 0644]
services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java
services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java

index e77dd7b..7a5a6c5 100644 (file)
@@ -2818,16 +2818,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
     @Override
     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
+            int displayId, DisplayCutout displayCutout) {
+        int width = fullWidth;
         // TODO(multi-display): Support navigation bar on secondary displays.
         if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
             // For a basic navigation bar, when we are in landscape mode we place
             // the navigation bar to the side.
             if (mNavigationBarCanMove && fullWidth > fullHeight) {
-                return fullWidth - getNavigationBarWidth(rotation, uiMode);
+                width -= getNavigationBarWidth(rotation, uiMode);
             }
         }
-        return fullWidth;
+        if (displayCutout != null) {
+            width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();
+        }
+        return width;
     }
 
     private int getNavigationBarHeight(int rotation, int uiMode) {
@@ -2840,35 +2844,46 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
     @Override
     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
+            int displayId, DisplayCutout displayCutout) {
+        int height = fullHeight;
         // TODO(multi-display): Support navigation bar on secondary displays.
         if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
             // For a basic navigation bar, when we are in portrait mode we place
             // the navigation bar to the bottom.
             if (!mNavigationBarCanMove || fullWidth < fullHeight) {
-                return fullHeight - getNavigationBarHeight(rotation, uiMode);
+                height -= getNavigationBarHeight(rotation, uiMode);
             }
         }
-        return fullHeight;
+        if (displayCutout != null) {
+            height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();
+        }
+        return height;
     }
 
     @Override
     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
-        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId);
+            int displayId, DisplayCutout displayCutout) {
+        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId,
+                displayCutout);
     }
 
     @Override
     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
+            int displayId, DisplayCutout displayCutout) {
         // There is a separate status bar at the top of the display.  We don't count that as part
         // of the fixed decor, since it can hide; however, for purposes of configurations,
         // we do want to exclude it since applications can't generally use that part
         // of the screen.
         // TODO(multi-display): Support status bars on secondary displays.
         if (displayId == DEFAULT_DISPLAY) {
-            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
-                    - mStatusBarHeight;
+            int statusBarHeight = mStatusBarHeight;
+            if (displayCutout != null) {
+                // If there is a cutout, it may already have accounted for some part of the status
+                // bar height.
+                statusBarHeight = Math.max(0, mStatusBarHeight - displayCutout.getSafeInsetTop());
+            }
+            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId,
+                    displayCutout) - statusBarHeight;
         }
         return fullHeight;
     }
@@ -6905,17 +6920,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
     @Override
     public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
-            Rect outInsets) {
+            DisplayCutout displayCutout, Rect outInsets) {
         outInsets.setEmpty();
 
         // Navigation bar and status bar.
-        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets);
-        outInsets.top = mStatusBarHeight;
+        getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, displayCutout, outInsets);
+        outInsets.top = Math.max(outInsets.top, mStatusBarHeight);
     }
 
     @Override
     public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
-            Rect outInsets) {
+            DisplayCutout displayCutout, Rect outInsets) {
         outInsets.setEmpty();
 
         // Only navigation bar
@@ -6929,6 +6944,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode);
             }
         }
+
+        if (displayCutout != null) {
+            outInsets.left += displayCutout.getSafeInsetLeft();
+            outInsets.top += displayCutout.getSafeInsetTop();
+            outInsets.right += displayCutout.getSafeInsetRight();
+            outInsets.bottom += displayCutout.getSafeInsetBottom();
+        }
     }
 
     @Override
index e9c4c5c..dde4bc8 100644 (file)
@@ -922,7 +922,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
      * button bar.
      */
     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation,
-            int uiMode, int displayId);
+            int uiMode, int displayId, DisplayCutout displayCutout);
 
     /**
      * Return the display height available after excluding any screen
@@ -930,25 +930,25 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
      * button bar.
      */
     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation,
-            int uiMode, int displayId);
+            int uiMode, int displayId, DisplayCutout displayCutout);
 
     /**
      * Return the available screen width that we should report for the
      * configuration.  This must be no larger than
-     * {@link #getNonDecorDisplayWidth(int, int, int, int int, int)}; it may be smaller than
-     * that to account for more transient decoration like a status bar.
+     * {@link #getNonDecorDisplayWidth(int, int, int, int, int, DisplayCutout)}; it may be smaller
+     * than that to account for more transient decoration like a status bar.
      */
     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation,
-            int uiMode, int displayId);
+            int uiMode, int displayId, DisplayCutout displayCutout);
 
     /**
      * Return the available screen height that we should report for the
      * configuration.  This must be no larger than
-     * {@link #getNonDecorDisplayHeight(int, int, int, int, int)}; it may be smaller than
-     * that to account for more transient decoration like a status bar.
+     * {@link #getNonDecorDisplayHeight(int, int, int, int, int, DisplayCutout)}; it may be smaller
+     * than that to account for more transient decoration like a status bar.
      */
     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation,
-            int uiMode, int displayId);
+            int uiMode, int displayId, DisplayCutout displayCutout);
 
     /**
      * Return whether the given window can become the Keyguard window. Typically returns true for
@@ -1639,10 +1639,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
      * @param displayRotation the current display rotation
      * @param displayWidth the current display width
      * @param displayHeight the current display height
+     * @param displayCutout the current display cutout
      * @param outInsets the insets to return
      */
     public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
-            Rect outInsets);
+            DisplayCutout displayCutout, Rect outInsets);
 
 
     /**
@@ -1666,10 +1667,11 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
      * @param displayRotation the current display rotation
      * @param displayWidth the current display width
      * @param displayHeight the current display height
+     * @param displayCutout the current display cutout
      * @param outInsets the insets to return
      */
     public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
-            Rect outInsets);
+            DisplayCutout displayCutout, Rect outInsets);
 
     /**
      * @return True if a specified {@param dockSide} is allowed on the current device, or false
index 841586a..473eeda 100644 (file)
@@ -138,7 +138,6 @@ import android.os.Trace;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.MutableBoolean;
-import android.util.Size;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
@@ -1160,10 +1159,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         }
 
         // Update application display metrics.
+        final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(
+                mRotation);
         final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation, uiMode,
-                mDisplayId);
+                mDisplayId, displayCutout);
         final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation, uiMode,
-                mDisplayId);
+                mDisplayId, displayCutout);
         mDisplayInfo.rotation = mRotation;
         mDisplayInfo.logicalWidth = dw;
         mDisplayInfo.logicalHeight = dh;
@@ -1174,7 +1175,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
             mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics,
                     CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
         }
-        mDisplayInfo.displayCutout = calculateDisplayCutoutForCurrentRotation();
+        mDisplayInfo.displayCutout = displayCutout;
         mDisplayInfo.getAppMetrics(mDisplayMetrics);
         if (mDisplayScalingDisabled) {
             mDisplayInfo.flags |= Display.FLAG_SCALING_DISABLED;
@@ -1196,18 +1197,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         return mDisplayInfo;
     }
 
-    DisplayCutout calculateDisplayCutoutForCurrentRotation() {
+    DisplayCutout calculateDisplayCutoutForRotation(int rotation) {
         final DisplayCutout cutout = mInitialDisplayCutout;
         if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
             return cutout;
         }
-        if (mRotation == ROTATION_0) {
+        if (rotation == ROTATION_0) {
             return cutout.computeSafeInsets(mInitialDisplayWidth, mInitialDisplayHeight);
         }
-        final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270);
+        final boolean rotated = (rotation == ROTATION_90 || mRotation == ROTATION_270);
         final Path bounds = cutout.getBounds().getBoundaryPath();
-        transformPhysicalToLogicalCoordinates(mRotation, mInitialDisplayWidth,
-                mInitialDisplayHeight, mTmpMatrix);
+        transformPhysicalToLogicalCoordinates(rotation, mInitialDisplayWidth, mInitialDisplayHeight,
+                mTmpMatrix);
         bounds.transform(mTmpMatrix);
         return DisplayCutout.fromBounds(bounds).computeSafeInsets(
                 rotated ? mInitialDisplayHeight : mInitialDisplayWidth,
@@ -1228,14 +1229,16 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         // so the display can be configured for things like fullscreen.
         config.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
 
+        final float density = mDisplayMetrics.density;
         config.screenWidthDp =
                 (int)(mService.mPolicy.getConfigDisplayWidth(dw, dh, displayInfo.rotation,
-                        config.uiMode, mDisplayId) / mDisplayMetrics.density);
+                        config.uiMode, mDisplayId, displayInfo.displayCutout) / density);
         config.screenHeightDp =
                 (int)(mService.mPolicy.getConfigDisplayHeight(dw, dh, displayInfo.rotation,
-                        config.uiMode, mDisplayId) / mDisplayMetrics.density);
+                        config.uiMode, mDisplayId, displayInfo.displayCutout) / density);
 
-        mService.mPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh, mTmpRect);
+        mService.mPolicy.getNonDecorInsetsLw(displayInfo.rotation, dw, dh,
+                displayInfo.displayCutout, mTmpRect);
         final int leftInset = mTmpRect.left;
         final int topInset = mTmpRect.top;
         // appBounds at the root level should mirror the app screen size.
@@ -1246,7 +1249,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                 || displayInfo.rotation == Surface.ROTATION_270);
 
         computeSizeRangesAndScreenLayout(displayInfo, mDisplayId, rotated, config.uiMode, dw, dh,
-                mDisplayMetrics.density, config);
+                density, config);
 
         config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK)
                 | ((displayInfo.flags & Display.FLAG_ROUND) != 0
@@ -1358,9 +1361,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
             DisplayMetrics dm, int dw, int dh, int displayId) {
         dm.noncompatWidthPixels = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
-                displayId);
+                displayId, mDisplayInfo.displayCutout);
         dm.noncompatHeightPixels = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
-                uiMode, displayId);
+                uiMode, displayId, mDisplayInfo.displayCutout);
         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
         if (curSize == 0 || size < curSize) {
@@ -1412,8 +1415,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
             int uiMode, int displayId) {
         // Get the app screen size at this rotation.
-        int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId);
-        int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId);
+        int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId,
+                mDisplayInfo.displayCutout);
+        int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId,
+                mDisplayInfo.displayCutout);
 
         // Compute the screen layout size class for this rotation.
         int longSize = w;
@@ -1430,8 +1435,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
 
     private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int displayId, int rotation,
             int uiMode, int dw, int dh) {
+        final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation);
         final int width = mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, uiMode,
-                displayId);
+                displayId, displayCutout);
         if (width < displayInfo.smallestNominalAppWidth) {
             displayInfo.smallestNominalAppWidth = width;
         }
@@ -1439,7 +1445,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
             displayInfo.largestNominalAppWidth = width;
         }
         final int height = mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
-                displayId);
+                displayId, displayCutout);
         if (height < displayInfo.smallestNominalAppHeight) {
             displayInfo.smallestNominalAppHeight = height;
         }
index 80798bf..423be63 100644 (file)
@@ -44,6 +44,7 @@ import android.os.RemoteException;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
+import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.IDockedStackListener;
 import android.view.animation.AnimationUtils;
@@ -173,6 +174,9 @@ public class DockedStackDividerController {
             final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
                     getContentWidth());
 
+            DisplayCutout displayCutout = mDisplayContent.calculateDisplayCutoutForRotation(
+                    rotation);
+
             // Since we only care about feasible states, snap to the closest snap target, like it
             // would happen when actually rotating the screen.
             final int snappedPosition = mSnapAlgorithmForRotation[rotation]
@@ -180,7 +184,7 @@ public class DockedStackDividerController {
             DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, mTmpRect,
                     mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
             mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
-                    mTmpRect3);
+                    displayCutout, mTmpRect3);
             mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
             minWidth = Math.min(mTmpRect.width(), minWidth);
         }
@@ -190,7 +194,7 @@ public class DockedStackDividerController {
     void getHomeStackBoundsInDockedMode(Rect outBounds) {
         final DisplayInfo di = mDisplayContent.getDisplayInfo();
         mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
-                mTmpRect);
+                di.displayCutout, mTmpRect);
         int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
         Configuration configuration = mDisplayContent.getConfiguration();
         // The offset in the left (landscape)/top (portrait) is calculated with the minimized
@@ -228,28 +232,29 @@ public class DockedStackDividerController {
             final int dh = rotated
                     ? mDisplayContent.mBaseDisplayWidth
                     : mDisplayContent.mBaseDisplayHeight;
-            mService.mPolicy.getStableInsetsLw(rotation, dw, dh, mTmpRect);
+            final DisplayCutout displayCutout =
+                    mDisplayContent.calculateDisplayCutoutForRotation(rotation);
+            mService.mPolicy.getStableInsetsLw(rotation, dw, dh, displayCutout, mTmpRect);
             config.unset();
             config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
 
             final int displayId = mDisplayContent.getDisplayId();
             final int appWidth = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation,
-                baseConfig.uiMode, displayId);
+                baseConfig.uiMode, displayId, displayCutout);
             final int appHeight = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
-                baseConfig.uiMode, displayId);
-            mService.mPolicy.getNonDecorInsetsLw(rotation, dw, dh, mTmpRect);
+                baseConfig.uiMode, displayId, mDisplayContent.getDisplayInfo().displayCutout);
+            mService.mPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect);
             final int leftInset = mTmpRect.left;
             final int topInset = mTmpRect.top;
 
             config.windowConfiguration.setAppBounds(leftInset /*left*/, topInset /*top*/,
                     leftInset + appWidth /*right*/, topInset + appHeight /*bottom*/);
 
-            config.screenWidthDp = (int)
-                    (mService.mPolicy.getConfigDisplayWidth(dw, dh, rotation, baseConfig.uiMode,
-                            displayId) / mDisplayContent.getDisplayMetrics().density);
-            config.screenHeightDp = (int)
-                    (mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, baseConfig.uiMode,
-                            displayId) / mDisplayContent.getDisplayMetrics().density);
+            final float density = mDisplayContent.getDisplayMetrics().density;
+            config.screenWidthDp = (int) (mService.mPolicy.getConfigDisplayWidth(dw, dh,
+                    rotation, baseConfig.uiMode, displayId, displayCutout) / density);
+            config.screenHeightDp = (int) (mService.mPolicy.getConfigDisplayHeight(dw, dh,
+                    rotation, baseConfig.uiMode, displayId, displayCutout) / density);
             final Context rotationContext = mService.mContext.createConfigurationContext(config);
             mSnapAlgorithmForRotation[rotation] = new DividerSnapAlgorithm(
                     rotationContext.getResources(), dw, dh, getContentWidth(),
index 62519e1..6966f1b 100644 (file)
@@ -480,7 +480,7 @@ class PinnedStackController {
     private void getInsetBounds(Rect outRect) {
         synchronized (mService.mWindowMap) {
             mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth,
-                    mDisplayInfo.logicalHeight, mTmpInsets);
+                    mDisplayInfo.logicalHeight, mDisplayInfo.displayCutout, mTmpInsets);
             outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
                     mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
                     mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
index e7547bf..ddb67b4 100644 (file)
@@ -23,6 +23,7 @@ import android.os.Looper;
 import android.os.Message;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -253,12 +254,13 @@ public class StackWindowController
             final TaskStack stack = mContainer;
             final DisplayContent displayContent = stack.getDisplayContent();
             final DisplayInfo di = displayContent.getDisplayInfo();
+            final DisplayCutout displayCutout = di.displayCutout;
 
             // Get the insets and display bounds
             mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
-                    mTmpStableInsets);
+                    displayCutout, mTmpStableInsets);
             mService.mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
-                    mTmpNonDecorInsets);
+                    displayCutout, mTmpNonDecorInsets);
             mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
 
             int width;
index a0d1480..ba08fcd 100644 (file)
@@ -552,13 +552,14 @@ public class TaskStack extends WindowContainer<Task> implements
         final int dockSide = getDockSide(outBounds);
         final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
                 dockSide, dividerSize);
-        final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
-        final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
+        final int displayWidth = displayInfo.logicalWidth;
+        final int displayHeight = displayInfo.logicalHeight;
 
         // Snap the position to a target.
         final int rotation = displayInfo.rotation;
         final int orientation = mDisplayContent.getConfiguration().orientation;
-        mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
+        mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight,
+                displayInfo.displayCutout, outBounds);
         final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
                 mService.mContext.getResources(), displayWidth, displayHeight,
                 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
@@ -929,7 +930,7 @@ public class TaskStack extends WindowContainer<Task> implements
             // adjusted to occupy whatever screen space the docked stack isn't occupying.
             final DisplayInfo di = mDisplayContent.getDisplayInfo();
             mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
-                    mTmpRect2);
+                    di.displayCutout, mTmpRect2);
             final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
                     di.logicalWidth,
                     di.logicalHeight,
index 966f622..ace0944 100644 (file)
@@ -6873,7 +6873,8 @@ public class WindowManagerService extends IWindowManager.Stub
         final DisplayContent dc = mRoot.getDisplayContent(displayId);
         if (dc != null) {
             final DisplayInfo di = dc.getDisplayInfo();
-            mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
+            mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                    di.displayCutout, outInsets);
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerInsetsTest.java
new file mode 100644 (file)
index 0000000..7e18ce7
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ErrorCollector;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class PhoneWindowManagerInsetsTest extends PhoneWindowManagerTestBase {
+
+    @Rule
+    public final ErrorCollector mErrorCollector = new ErrorCollector();
+
+    @Before
+    public void setUp() throws Exception {
+        addStatusBar();
+        addNavigationBar();
+    }
+
+    @Test
+    public void portrait() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_0, false /* withCutout */);
+
+        verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT);
+        verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT);
+        verifyConsistency(di);
+    }
+
+    @Test
+    public void portrait_withCutout() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_0, true /* withCutout */);
+
+        verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT);
+        verifyNonDecorInsets(di, 0, DISPLAY_CUTOUT_HEIGHT, 0, NAV_BAR_HEIGHT);
+        verifyConsistency(di);
+    }
+
+    @Test
+    public void landscape() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_90, false /* withCutout */);
+
+        verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
+        verifyNonDecorInsets(di, 0, 0, NAV_BAR_HEIGHT, 0);
+        verifyConsistency(di);
+    }
+
+    @Test
+    public void landscape_withCutout() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_90, true /* withCutout */);
+
+        verifyStableInsets(di, DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0);
+        verifyNonDecorInsets(di, DISPLAY_CUTOUT_HEIGHT, 0, NAV_BAR_HEIGHT, 0);
+        verifyConsistency(di);
+    }
+
+    @Test
+    public void seascape() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_270, false /* withCutout */);
+
+        verifyStableInsets(di, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0);
+        verifyNonDecorInsets(di, NAV_BAR_HEIGHT, 0, 0, 0);
+        verifyConsistency(di);
+    }
+
+    @Test
+    public void seascape_withCutout() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_270, true /* withCutout */);
+
+        verifyStableInsets(di, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0);
+        verifyNonDecorInsets(di, NAV_BAR_HEIGHT, 0, DISPLAY_CUTOUT_HEIGHT, 0);
+        verifyConsistency(di);
+    }
+
+    @Test
+    public void upsideDown() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_180, false /* withCutout */);
+
+        verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT);
+        verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT);
+        verifyConsistency(di);
+    }
+
+    @Test
+    public void upsideDown_withCutout() throws Exception {
+        DisplayInfo di = displayInfoForRotation(ROTATION_180, true /* withCutout */);
+
+        verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT + DISPLAY_CUTOUT_HEIGHT);
+        verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT + DISPLAY_CUTOUT_HEIGHT);
+        verifyConsistency(di);
+    }
+
+    private void verifyStableInsets(DisplayInfo di, int left, int top, int right, int bottom) {
+        mErrorCollector.checkThat("stableInsets", getStableInsetsLw(di), equalTo(new Rect(
+                left, top, right, bottom)));
+    }
+
+    private void verifyNonDecorInsets(DisplayInfo di, int left, int top, int right, int bottom) {
+        mErrorCollector.checkThat("nonDecorInsets", getNonDecorInsetsLw(di), equalTo(new Rect(
+                left, top, right, bottom)));
+    }
+
+    private void verifyConsistency(DisplayInfo di) {
+        verifyConsistency("configDisplay", di, getStableInsetsLw(di),
+                getConfigDisplayWidth(di), getConfigDisplayHeight(di));
+        verifyConsistency("nonDecorDisplay", di, getNonDecorInsetsLw(di),
+                getNonDecorDisplayWidth(di), getNonDecorDisplayHeight(di));
+    }
+
+    private void verifyConsistency(String what, DisplayInfo di, Rect insets, int width,
+            int height) {
+        mErrorCollector.checkThat(what + ":width", width,
+                equalTo(di.logicalWidth - insets.left - insets.right));
+        mErrorCollector.checkThat(what + ":height", height,
+                equalTo(di.logicalHeight - insets.top - insets.bottom));
+    }
+
+    private Rect getStableInsetsLw(DisplayInfo di) {
+        Rect result = new Rect();
+        mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                di.displayCutout, result);
+        return result;
+    }
+
+    private Rect getNonDecorInsetsLw(DisplayInfo di) {
+        Rect result = new Rect();
+        mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                di.displayCutout, result);
+        return result;
+    }
+
+    private int getNonDecorDisplayWidth(DisplayInfo di) {
+        return mPolicy.getNonDecorDisplayWidth(di.logicalWidth, di.logicalHeight, di.rotation,
+                0 /* ui */, Display.DEFAULT_DISPLAY, di.displayCutout);
+    }
+
+    private int getNonDecorDisplayHeight(DisplayInfo di) {
+        return mPolicy.getNonDecorDisplayHeight(di.logicalWidth, di.logicalHeight, di.rotation,
+                0 /* ui */, Display.DEFAULT_DISPLAY, di.displayCutout);
+    }
+
+    private int getConfigDisplayWidth(DisplayInfo di) {
+        return mPolicy.getConfigDisplayWidth(di.logicalWidth, di.logicalHeight, di.rotation,
+                0 /* ui */, Display.DEFAULT_DISPLAY, di.displayCutout);
+    }
+
+    private int getConfigDisplayHeight(DisplayInfo di) {
+        return mPolicy.getConfigDisplayHeight(di.logicalWidth, di.logicalHeight, di.rotation,
+                0 /* ui */, Display.DEFAULT_DISPLAY, di.displayCutout);
+    }
+}
\ No newline at end of file
index ad89953..30ca9ca 100644 (file)
@@ -72,7 +72,6 @@ public class PhoneWindowManagerTestBase {
     FakeWindowState mNavigationBar;
     private boolean mHasDisplayCutout;
     private int mRotation = ROTATION_0;
-    private final Matrix mTmpMatrix = new Matrix();
 
     @Before
     public void setUpBase() throws Exception {
@@ -97,24 +96,7 @@ public class PhoneWindowManagerTestBase {
     }
 
     private void updateDisplayFrames() {
-        DisplayInfo info = new DisplayInfo();
-
-        final boolean flippedDimensions = mRotation == ROTATION_90 || mRotation == ROTATION_270;
-        info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
-        info.logicalHeight = flippedDimensions ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
-        info.rotation = mRotation;
-        if (mHasDisplayCutout) {
-            Path p = new Path();
-            p.addRect(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT,
-                    Path.Direction.CCW);
-            transformPhysicalToLogicalCoordinates(
-                    mRotation, DISPLAY_WIDTH, DISPLAY_HEIGHT, mTmpMatrix);
-            p.transform(mTmpMatrix);
-            info.displayCutout = DisplayCutout.fromBounds(p);
-        } else {
-            info.displayCutout = null;
-        }
-
+        DisplayInfo info = displayInfoForRotation(mRotation, mHasDisplayCutout);
         mFrames = new DisplayFrames(Display.DEFAULT_DISPLAY, info);
     }
 
@@ -161,6 +143,34 @@ public class PhoneWindowManagerTestBase {
         assertInsetBy(actual, 0, expectedInsetTop, 0, expectedInsetBottom);
     }
 
+    public static DisplayInfo displayInfoForRotation(int rotation, boolean withDisplayCutout) {
+        DisplayInfo info = new DisplayInfo();
+
+        final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270;
+        info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
+        info.logicalHeight = flippedDimensions ? DISPLAY_WIDTH : DISPLAY_HEIGHT;
+        info.rotation = rotation;
+        if (withDisplayCutout) {
+            info.displayCutout = displayCutoutForRotation(rotation)
+                    .computeSafeInsets(info.logicalWidth, info.logicalHeight);
+        } else {
+            info.displayCutout = null;
+        }
+        return info;
+    }
+
+    private static DisplayCutout displayCutoutForRotation(int rotation) {
+        Path p = new Path();
+        p.addRect(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT,
+                Path.Direction.CCW);
+
+        Matrix m = new Matrix();
+        transformPhysicalToLogicalCoordinates(rotation, DISPLAY_WIDTH, DISPLAY_HEIGHT, m);
+        p.transform(m);
+
+        return DisplayCutout.fromBounds(p);
+    }
+
     static class TestContextWrapper extends ContextWrapper {
         private final TestableResources mResourceMocker;
 
index 7a55904..0b99eaa 100644 (file)
@@ -45,6 +45,7 @@ import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.view.Display;
+import android.view.DisplayCutout;
 import android.view.IWindowManager;
 import android.view.InputChannel;
 import android.view.KeyEvent;
@@ -169,25 +170,25 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
 
     @Override
     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
+            int displayId, DisplayCutout displayCutout) {
         return 0;
     }
 
     @Override
     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
+            int displayId, DisplayCutout displayCutout) {
         return 0;
     }
 
     @Override
     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
+            int displayId, DisplayCutout displayCutout) {
         return 0;
     }
 
     @Override
     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
-            int displayId) {
+            int displayId, DisplayCutout displayCutout) {
         return 0;
     }
 
@@ -589,7 +590,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
 
     @Override
     public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
-            Rect outInsets) {
+            DisplayCutout cutout, Rect outInsets) {
 
     }
 
@@ -606,7 +607,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
 
     @Override
     public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
-            Rect outInsets) {
+            DisplayCutout cutout, Rect outInsets) {
 
     }