Use WC bounds for insets calculation

When computing insets based on navigation bar and status bar, use the
window's bounds instead of display bounds to ensure it compenstates for
the display area. The system bars should use their bounds to ensure
they aren't creating insets outside the display area. The window bounds
are also used when calculating the size and placement of the system
bars.

Bug: 156676090
Test: DisplayPolicyLayoutTests
Test: DisplayPolicyInsetsTests
Test: InsetsPolicyTest
Test: InsetsSourceProviderTest
Test: InsetsStateControllerTest
Change-Id: I9a3481fcd0146463c10077967b49bf46190f7946
This commit is contained in:
chaviw
2020-04-21 17:26:36 -07:00
parent 85cac3bc25
commit c9889ea63c
5 changed files with 58 additions and 30 deletions

View File

@@ -1037,8 +1037,8 @@ public class DisplayPolicy {
mStatusBarController.setWindow(win);
final TriConsumer<DisplayFrames, WindowState, Rect> frameProvider =
(displayFrames, windowState, rect) -> {
rect.top = 0;
rect.bottom = getStatusBarHeight(displayFrames);
rect.set(windowState.getFrameLw());
rect.bottom = rect.top + getStatusBarHeight(displayFrames);
};
mDisplayContent.setInsetProvider(ITYPE_STATUS_BAR, win, frameProvider);
mDisplayContent.setInsetProvider(ITYPE_TOP_GESTURES, win, frameProvider);
@@ -1058,8 +1058,7 @@ public class DisplayPolicy {
displayFrames.mDisplayHeight,
displayFrames.mRotation) == NAV_BAR_BOTTOM
&& !mNavButtonForcedVisible) {
sTmpRect.set(displayFrames.mUnrestricted);
sTmpRect.set(windowState.getFrameLw());
sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
inOutFrame.top = sTmpRect.bottom
- getNavigationBarHeight(displayFrames.mRotation,
@@ -1687,12 +1686,11 @@ public class DisplayPolicy {
if (isSimulatedLayout) {
w.setSimulatedWindowFrames(simulatedFrames);
}
Rect bounds = w.getBounds();
final WindowFrames windowFrames = w.getLayoutingWindowFrames();
windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
displayFrames.mUnrestricted /* displayFrame */,
displayFrames.mUnrestricted /* contentFrame */,
displayFrames.mUnrestricted /* visibleFrame */, sTmpRect /* decorFrame */,
displayFrames.mUnrestricted /* stableFrame */);
windowFrames.setFrames(bounds /* parentFrame */, bounds /* displayFrame */,
bounds /* contentFrame */, bounds /* visibleFrame */, sTmpRect /* decorFrame */,
bounds /* stableFrame */);
try {
w.computeFrame(displayFrames);
} finally {
@@ -1749,14 +1747,13 @@ public class DisplayPolicy {
if (mStatusBar == null) {
return false;
}
// apply any navigation bar insets
// apply any status bar insets
Rect bounds = mStatusBar.getBounds();
sTmpRect.setEmpty();
final WindowFrames windowFrames = mStatusBar.getLayoutingWindowFrames();
windowFrames.setFrames(displayFrames.mUnrestricted /* parentFrame */,
displayFrames.mUnrestricted /* displayFrame */,
displayFrames.mStable /* contentFrame */,
displayFrames.mStable /* visibleFrame */, sTmpRect /* decorFrame */,
displayFrames.mStable /* stableFrame */);
windowFrames.setFrames(bounds /* parentFrame */, bounds /* displayFrame */,
bounds /* contentFrame */, bounds /* visibleFrame */, sTmpRect /* decorFrame */,
bounds /* stableFrame */);
// Let the status bar determine its size.
mStatusBar.computeFrame(displayFrames);
@@ -1827,18 +1824,20 @@ public class DisplayPolicy {
final Rect dockFrame = displayFrames.mDock;
final int navBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation);
navigationFrame.set(mNavigationBar.getBounds());
final Rect cutoutSafeUnrestricted = sTmpRect;
cutoutSafeUnrestricted.set(displayFrames.mUnrestricted);
cutoutSafeUnrestricted.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
if (navBarPosition == NAV_BAR_BOTTOM) {
// It's a system nav bar or a portrait screen; nav bar goes on bottom.
final int topNavBar = cutoutSafeUnrestricted.bottom
final int topNavBar = Math.min(cutoutSafeUnrestricted.bottom, navigationFrame.bottom)
- getNavigationBarFrameHeight(rotation, uiMode);
final int top = mNavButtonForcedVisible
? topNavBar
: cutoutSafeUnrestricted.bottom - getNavigationBarHeight(rotation, uiMode);
navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
final int top = mNavButtonForcedVisible ? topNavBar :
Math.min(cutoutSafeUnrestricted.bottom, navigationFrame.bottom)
- getNavigationBarHeight(rotation, uiMode);
navigationFrame.top = topNavBar;
displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -1858,9 +1857,9 @@ public class DisplayPolicy {
}
} else if (navBarPosition == NAV_BAR_RIGHT) {
// Landscape screen; nav bar goes to the right.
final int left = cutoutSafeUnrestricted.right
final int left = Math.min(cutoutSafeUnrestricted.right, navigationFrame.right)
- getNavigationBarWidth(rotation, uiMode);
navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
navigationFrame.left = left;
displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -1880,9 +1879,9 @@ public class DisplayPolicy {
}
} else if (navBarPosition == NAV_BAR_LEFT) {
// Seascape screen; nav bar goes to the left.
final int right = cutoutSafeUnrestricted.left
final int right = Math.max(cutoutSafeUnrestricted.left, navigationFrame.left)
+ getNavigationBarWidth(rotation, uiMode);
navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
navigationFrame.right = right;
displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -2065,7 +2064,7 @@ public class DisplayPolicy {
final @InsetsType int typesToFit = attrs.getFitInsetsTypes();
final @InsetsSide int sidesToFit = attrs.getFitInsetsSides();
final ArraySet<Integer> types = InsetsState.toInternalType(typesToFit);
final Rect dfu = displayFrames.mUnrestricted;
final Rect dfu = win.getBounds();
Insets insets = Insets.of(0, 0, 0, 0);
for (int i = types.size() - 1; i >= 0; i--) {
final InsetsSource source = mDisplayContent.getInsetsPolicy()

View File

@@ -462,7 +462,10 @@ class InsetsSourceProvider {
mCapturedLeash = animationLeash;
final Rect frame = mWin.getWindowFrames().mFrame;
t.setPosition(mCapturedLeash, frame.left, frame.top);
Point position = new Point();
mWin.transformFrameToSurfacePosition(frame.left, frame.top, position);
t.setPosition(mCapturedLeash, position.x, position.y);
}
@Override

View File

@@ -5387,7 +5387,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
private void transformFrameToSurfacePosition(int left, int top, Point outPoint) {
void transformFrameToSurfacePosition(int left, int top, Point outPoint) {
outPoint.set(left, top);
// If changed, also adjust getTransformationMatrix

View File

@@ -43,11 +43,15 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
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.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.testng.Assert.expectThrows;
@@ -61,6 +65,7 @@ import android.util.SparseArray;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.InsetsState;
import android.view.View;
import android.view.WindowInsets.Side;
import android.view.WindowInsets.Type;
import android.view.WindowManager;
@@ -95,6 +100,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
private boolean mIsLongEdgeDisplayCutout;
private static final int DECOR_WINDOW_INSET = 50;
private final Rect mDisplayBounds = new Rect();
@Before
public void setUp() throws Exception {
mWindow = spy(createWindow(null, TYPE_APPLICATION, "window"));
@@ -107,6 +114,15 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
attrs.height = MATCH_PARENT;
attrs.format = PixelFormat.TRANSLUCENT;
spyOn(mStatusBarWindow);
spyOn(mNavBarWindow);
// Disabling this call for most tests since it can override the systemUiFlags when called.
doReturn(0).when(mDisplayPolicy).updateSystemUiVisibilityLw();
mDisplayPolicy.mLastSystemUiFlags |= View.STATUS_BAR_TRANSPARENT;
mDisplayPolicy.mLastSystemUiFlags |= View.NAVIGATION_BAR_TRANSPARENT;
updateDisplayFrames();
}
@@ -128,7 +144,12 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
private void updateDisplayFrames() {
mFrames = createDisplayFrames();
mDisplayBounds.set(0, 0, mFrames.mDisplayWidth, mFrames.mDisplayHeight);
mDisplayContent.mDisplayFrames = mFrames;
doReturn(mDisplayBounds).when(mStatusBarWindow).getBounds();
doReturn(mDisplayBounds).when(mNavBarWindow).getBounds();
doReturn(mDisplayBounds).when(mWindow).getBounds();
}
private DisplayFrames createDisplayFrames() {
@@ -808,6 +829,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
@Test
public void forceShowSystemBars_clearsSystemUIFlags() {
doCallRealMethod().when(mDisplayPolicy).updateSystemUiVisibilityLw();
mDisplayPolicy.mLastSystemUiFlags |= SYSTEM_UI_FLAG_FULLSCREEN;
mWindow.mAttrs.subtreeSystemUiVisibility |= SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
mWindow.mAttrs.flags =
@@ -829,12 +851,15 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
@Test
public void testScreenDecorWindows() {
final WindowState decorWindow = createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow");
final WindowState decorWindow = spy(
createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow"));
mWindow.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR
| FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
decorWindow.mAttrs.privateFlags |= PRIVATE_FLAG_IS_SCREEN_DECOR;
addWindow(decorWindow);
addWindow(mWindow);
doReturn(new Rect(0, 0, mFrames.mDisplayWidth, mFrames.mDisplayHeight))
.when(decorWindow).getBounds();
// Decor on top
updateDecorWindow(decorWindow, MATCH_PARENT, DECOR_WINDOW_INSET, TOP);

View File

@@ -27,7 +27,7 @@ import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
import static org.junit.Assert.assertEquals;
@@ -68,7 +68,8 @@ public class DisplayPolicyTestsBase extends WindowTestsBase {
@Before
public void setUpDisplayPolicy() {
mDisplayPolicy = spy(mDisplayContent.getDisplayPolicy());
mDisplayPolicy = mDisplayContent.getDisplayPolicy();
spyOn(mDisplayPolicy);
final TestContextWrapper context = new TestContextWrapper(
mDisplayPolicy.getContext(), mDisplayPolicy.getCurrentUserResources());