From 44a65980e19964f3cd0cac01f31d042db91b507d Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Thu, 25 Mar 2021 21:13:28 +0800 Subject: [PATCH] Refine isLightBarAllowed The light bar is only allowed if the color-controlling window has intersection with the system bar. The app window frame doesn't need to 'contains' the frame of the bar, because: 1. In split-screen mode, the app window only intersects a part of status bar. 2. When navigation bar is at the same side of a display cutout, navigation bar would be thicker than the cutout. The app window which fits the cutout can only intersect with a part of navigation bar. Fix: 183696228 Test: atest LetterboxTest LightBarTests DisplayPolicyTests Change-Id: If17a2050b22e674bb760d6c98305ee69067b11fe --- .../com/android/server/wm/ActivityRecord.java | 8 --- .../com/android/server/wm/DisplayPolicy.java | 52 ++++++------------- .../java/com/android/server/wm/Letterbox.java | 23 -------- .../server/wm/LetterboxUiController.java | 8 --- .../com/android/server/wm/WindowState.java | 4 -- .../android/server/wm/DisplayPolicyTests.java | 15 +++++- .../com/android/server/wm/LetterboxTest.java | 15 ------ 7 files changed, 30 insertions(+), 95 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c39358e7ad4aa..67e28bb10067f 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1417,14 +1417,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return mLetterboxUiController.isFullyTransparentBarAllowed(rect); } - /** - * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with - * the given {@code rect}. - */ - boolean isLetterboxOverlappingWith(Rect rect) { - return mLetterboxUiController.isLetterboxOverlappingWith(rect); - } - static class Token extends IApplicationToken.Stub { private WeakReference weakActivity; private final String name; diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 8c5470578e804..203214d536ddf 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -146,7 +146,6 @@ import android.view.View; import android.view.ViewDebug; import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; -import android.view.WindowInsetsController.Appearance; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; @@ -2495,12 +2494,10 @@ public class DisplayPolicy { mService.getRootTaskBounds(inSplitScreen ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_UNDEFINED, mNonDockedRootTaskBounds); - final int fullscreenAppearance = updateLightStatusBarLw(0 /* appearance */, - mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState, - mNonDockedRootTaskBounds); - final int dockedAppearance = updateLightStatusBarLw(0 /* appearance */, - mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState, - mDockedRootTaskBounds); + final int fullscreenAppearance = getStatusBarAppearance(mTopFullscreenOpaqueWindowState, + mTopFullscreenOpaqueOrDimmingWindowState); + final int dockedAppearance = getStatusBarAppearance(mTopDockedOpaqueWindowState, + mTopDockedOpaqueOrDimmingWindowState); final int disableFlags = win.getDisableFlags(); final int opaqueAppearance = updateSystemBarsLw(win, disableFlags); final WindowState navColorWin = chooseNavigationColorWindowLw( @@ -2560,30 +2557,12 @@ public class DisplayPolicy { return true; } - private int updateLightStatusBarLw(@Appearance int appearance, WindowState opaque, - WindowState opaqueOrDimming, Rect rootTaskBounds) { - final DisplayRotation displayRotation = mDisplayContent.getDisplayRotation(); - final int statusBarHeight = mStatusBarHeightForRotation[displayRotation.getRotation()]; - final boolean rootTaskBoundsContainStatusBar = - rootTaskBounds.isEmpty() ? false : rootTaskBounds.top < statusBarHeight; + private int getStatusBarAppearance(WindowState opaque, WindowState opaqueOrDimming) { final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded(); - final WindowState statusColorWin = onKeyguard ? mNotificationShade : opaqueOrDimming; - if (rootTaskBoundsContainStatusBar && statusColorWin != null) { - if (statusColorWin == opaque || onKeyguard) { - // If the top fullscreen-or-dimming window is also the top fullscreen, respect - // its light flag. - appearance &= ~APPEARANCE_LIGHT_STATUS_BARS; - appearance |= statusColorWin.mAttrs.insetsFlags.appearance - & APPEARANCE_LIGHT_STATUS_BARS; - } else if (statusColorWin.isDimming()) { - // Otherwise if it's dimming, clear the light flag. - appearance &= ~APPEARANCE_LIGHT_STATUS_BARS; - } - if (!isLightBarAllowed(statusColorWin, TYPE_STATUS_BAR)) { - appearance &= ~APPEARANCE_LIGHT_STATUS_BARS; - } - } - return appearance; + final WindowState colorWin = onKeyguard ? mNotificationShade : opaqueOrDimming; + return isLightBarAllowed(colorWin, ITYPE_STATUS_BAR) && (colorWin == opaque || onKeyguard) + ? (colorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS) + : 0; } @VisibleForTesting @@ -2642,9 +2621,9 @@ public class DisplayPolicy { // Clear the light flag for dimming window. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } - if (!isLightBarAllowed(navColorWin, TYPE_NAVIGATION_BAR)) { - appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; - } + } + if (!isLightBarAllowed(navColorWin, ITYPE_NAVIGATION_BAR)) { + appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } return appearance; } @@ -2697,11 +2676,12 @@ public class DisplayPolicy { return appearance; } - private boolean isLightBarAllowed(WindowState win, int windowType) { + private boolean isLightBarAllowed(WindowState win, @InternalInsetsType int type) { if (win == null) { - return true; + return false; } - return !win.isLetterboxedOverlappingWith(getBarContentFrameForWindow(win, windowType)); + final InsetsSource source = win.getInsetsState().peekSource(type); + return source != null && Rect.intersects(win.getFrame(), source.getFrame()); } private Rect getBarContentFrameForWindow(WindowState win, int windowType) { diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java index af82f755152c8..3dbe79df67220 100644 --- a/services/core/java/com/android/server/wm/Letterbox.java +++ b/services/core/java/com/android/server/wm/Letterbox.java @@ -149,18 +149,6 @@ public class Letterbox { return (emptyCount + noOverlappingCount) == mSurfaces.length; } - /** - * Returns true if any part of the letterbox overlaps with the given {@code rect}. - */ - public boolean isOverlappingWith(Rect rect) { - for (LetterboxSurface surface : mSurfaces) { - if (surface.isOverlappingWith(rect)) { - return true; - } - } - return false; - } - /** * Hides the letterbox. * @@ -339,17 +327,6 @@ public class Letterbox { return Math.max(0, mLayoutFrameGlobal.height()); } - /** - * Returns if the given {@code rect} overlaps with this letterbox piece. - * @param rect the area to check for overlap in global coordinates - */ - public boolean isOverlappingWith(Rect rect) { - if (mLayoutFrameGlobal.isEmpty()) { - return false; - } - return Rect.intersects(rect, mLayoutFrameGlobal); - } - public void applySurfaceChanges(SurfaceControl.Transaction t) { if (!needsApplySurfaceChanges()) { // Nothing changed. diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index 130f68097331b..05728cd35afc6 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -112,14 +112,6 @@ final class LetterboxUiController { return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect); } - /** - * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with - * the given {@code rect}. - */ - boolean isLetterboxOverlappingWith(Rect rect) { - return mLetterbox != null && mLetterbox.isOverlappingWith(rect); - } - void updateLetterboxSurface(WindowState winHint) { final WindowState w = mActivityRecord.findMainWindow(); if (w != winHint && winHint != null && w != null) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 1a5042ffd56db..2a0aca4d06b79 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -4001,10 +4001,6 @@ class WindowState extends WindowContainer implements WindowManagerP return mActivityRecord == null || mActivityRecord.isFullyTransparentBarAllowed(frame); } - public boolean isLetterboxedOverlappingWith(Rect rect) { - return mActivityRecord != null && mActivityRecord.isLetterboxOverlappingWith(rect); - } - boolean isDragResizeChanged() { return mDragResizing != computeDragResizing(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index c163ef152af68..2ca78533f8671 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -156,6 +156,7 @@ public class DisplayPolicyTests extends WindowTestsBase { opaque, dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); } + @UseTestDisplay(addWindows = { W_NAVIGATION_BAR }) @Test public void testUpdateLightNavigationBarLw() { DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); @@ -167,7 +168,19 @@ public class DisplayPolicyTests extends WindowTestsBase { final WindowState imeDrawDarkNavBar = createInputMethodWindow(true, true, false); final WindowState imeDrawLightNavBar = createInputMethodWindow(true, true, true); - assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, + mDisplayContent.setLayoutNeeded(); + mDisplayContent.performLayout(true /* initial */, false /* updateImeWindows */); + + final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR); + navSource.setFrame(mNavBarWindow.getFrame()); + opaqueDarkNavBar.mAboveInsetsState.addSource(navSource); + opaqueLightNavBar.mAboveInsetsState.addSource(navSource); + dimming.mAboveInsetsState.addSource(navSource); + imeDrawDarkNavBar.mAboveInsetsState.addSource(navSource); + imeDrawLightNavBar.mAboveInsetsState.addSource(navSource); + + // If there is no window, APPEARANCE_LIGHT_NAVIGATION_BARS is not allowed. + assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, null, null, null, null)); diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java index ee01b7fe57503..647a898a53614 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java @@ -66,12 +66,6 @@ public class LetterboxTest { mTransaction = spy(StubTransaction.class); } - @Test - public void testOverlappingWith_usesGlobalCoordinates() { - mLetterbox.layout(new Rect(0, 0, 10, 50), new Rect(0, 2, 10, 45), new Point(1000, 2000)); - assertTrue(mLetterbox.isOverlappingWith(new Rect(0, 0, 1, 1))); - } - private static final int TOP_BAR = 0x1; private static final int BOTTOM_BAR = 0x2; private static final int LEFT_BAR = 0x4; @@ -226,15 +220,6 @@ public class LetterboxTest { assertNotNull(mSurfaces.behind); } - @Test - public void testIsOverlappingWith_cornersRounded_doesNotCheckSurfaceBehind() { - mAreCornersRounded = true; - mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(0, 0)); - mLetterbox.applySurfaceChanges(mTransaction); - - assertFalse(mLetterbox.isOverlappingWith(new Rect(1, 2, 9, 9))); - } - @Test public void testNotIntersectsOrFullyContains_cornersRounded_doesNotCheckSurfaceBehind() { mAreCornersRounded = true;