@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) {
@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;
}
@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
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
* 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
* 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
* @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);
/**
* @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
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;
}
// 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;
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;
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,
// 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.
|| 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
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) {
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;
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;
}
displayInfo.largestNominalAppWidth = width;
}
final int height = mService.mPolicy.getConfigDisplayHeight(dw, dh, rotation, uiMode,
- displayId);
+ displayId, displayCutout);
if (height < displayInfo.smallestNominalAppHeight) {
displayInfo.smallestNominalAppHeight = height;
}
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;
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]
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);
}
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
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(),
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);
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;
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;
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,
// 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,
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);
}
}
--- /dev/null
+/*
+ * 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
FakeWindowState mNavigationBar;
private boolean mHasDisplayCutout;
private int mRotation = ROTATION_0;
- private final Matrix mTmpMatrix = new Matrix();
@Before
public void setUpBase() throws Exception {
}
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);
}
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;
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;
@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;
}
@Override
public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
- Rect outInsets) {
+ DisplayCutout cutout, Rect outInsets) {
}
@Override
public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
- Rect outInsets) {
+ DisplayCutout cutout, Rect outInsets) {
}