From c9889ea63c37dc107d87977c03faba91e5dfa8ed Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 21 Apr 2020 17:26:36 -0700 Subject: [PATCH] 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 --- .../com/android/server/wm/DisplayPolicy.java | 49 +++++++++---------- .../server/wm/InsetsSourceProvider.java | 5 +- .../com/android/server/wm/WindowState.java | 2 +- .../server/wm/DisplayPolicyLayoutTests.java | 27 +++++++++- .../server/wm/DisplayPolicyTestsBase.java | 5 +- 5 files changed, 58 insertions(+), 30 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index e8b0e0a4b121c..d2813e823465e 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1037,8 +1037,8 @@ public class DisplayPolicy { mStatusBarController.setWindow(win); final TriConsumer 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 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() diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index c8d9fe0f0a659..952966824f63c 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -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 diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 479a9037f869c..b795ce2b13909 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5387,7 +5387,7 @@ class WindowState extends WindowContainer 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 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 1922351ac1eb3..b69a1f3f7766c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -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); 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 7ba3fd815b2d0..1e1c3998670e4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java @@ -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());