Loading services/core/java/com/android/server/wm/DisplayPolicy.java +81 −74 Original line number Diff line number Diff line Loading @@ -315,6 +315,13 @@ public class DisplayPolicy { private WindowState mSystemUiControllingWindow; // Candidate window to determine the color of navigation bar. private WindowState mNavBarColorWindowCandidate; // The window to determine opacity and background of translucent navigation bar. The window // needs to be opaque. private WindowState mNavBarBackgroundWindow; private int mLastDisableFlags; private int mLastAppearance; private int mLastFullscreenAppearance; Loading Loading @@ -347,8 +354,6 @@ public class DisplayPolicy { private boolean mTopIsFullscreen; private boolean mForceStatusBar; private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; private boolean mForcingShowNavBar; private int mForcingShowNavBarLayer; private boolean mForceShowSystemBars; private boolean mShowingDream; Loading Loading @@ -1794,9 +1799,9 @@ public class DisplayPolicy { mTopFullscreenOpaqueOrDimmingWindowState = null; mTopDockedOpaqueWindowState = null; mTopDockedOpaqueOrDimmingWindowState = null; mNavBarColorWindowCandidate = null; mNavBarBackgroundWindow = null; mForceStatusBar = false; mForcingShowNavBar = false; mForcingShowNavBarLayer = -1; mAllowLockscreenWhenOn = false; mShowingDream = false; Loading @@ -1816,11 +1821,6 @@ public class DisplayPolicy { if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi); applyKeyguardPolicy(win, imeTarget); final int fl = attrs.flags; if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi && attrs.type == TYPE_INPUT_METHOD) { mForcingShowNavBar = true; mForcingShowNavBarLayer = win.getSurfaceLayer(); } boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type < FIRST_SYSTEM_WINDOW; Loading Loading @@ -1891,12 +1891,35 @@ public class DisplayPolicy { } } // Check if the freeform window overlaps with the navigation bar area. final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null; if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode() && isOverlappingWithNavBar(win, navBarWin)) { if (isOverlappingWithNavBar(win, navBarWin)) { // Check if the freeform window overlaps with the navigation bar area. if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()) { mIsFreeformWindowOverlappingWithNavBar = true; } // Cache app window that overlaps with the navigation bar area to determine opacity and // appearance of the navigation bar. We only need to cache one window because there // should be only one overlapping window if it's not in gesture navigation mode; if it's // in gesture navigation mode, the navigation bar will be NAV_BAR_FORCE_TRANSPARENT and // its appearance won't be decided by overlapping windows. if (affectsSystemUi) { if ((appWindow && attached == null && attrs.isFullscreen()) || attrs.type == TYPE_VOICE_INTERACTION) { if (mNavBarColorWindowCandidate == null) { mNavBarColorWindowCandidate = win; } if (mNavBarBackgroundWindow == null) { mNavBarBackgroundWindow = win; } } else if (win.isDimming()) { // For dimming window with it's host bounds overlapping with navigation bar, it // can be used to determine navigation bar's color but not opacity. if (mNavBarColorWindowCandidate == null) { mNavBarColorWindowCandidate = win; } } } } // Also keep track of any windows that are dimming but not necessarily fullscreen in the // docked root task. Loading Loading @@ -2646,15 +2669,12 @@ public class DisplayPolicy { mTopDockedOpaqueOrDimmingWindowState); final int disableFlags = win.getDisableFlags(); final int opaqueAppearance = updateSystemBarsLw(win, disableFlags); final WindowState navColorWin = chooseNavigationColorWindowLw( mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState, final WindowState navColorWin = chooseNavigationColorWindowLw(mNavBarColorWindowCandidate, mDisplayContent.mInputMethodWindow, mNavigationBarPosition); final boolean isNavbarColorManagedByIme = navColorWin != null && navColorWin == mDisplayContent.mInputMethodWindow; final int appearance = updateLightNavigationBarLw( win.mAttrs.insetsFlags.appearance, mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState, mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance; final int appearance = updateLightNavigationBarLw(win.mAttrs.insetsFlags.appearance, navColorWin) | opaqueAppearance; final int behavior = win.mAttrs.insetsFlags.behavior; final boolean isFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR) || !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR); Loading Loading @@ -2713,8 +2733,7 @@ public class DisplayPolicy { @VisibleForTesting @Nullable static WindowState chooseNavigationColorWindowLw(WindowState opaque, WindowState opaqueOrDimming, WindowState imeWindow, static WindowState chooseNavigationColorWindowLw(WindowState candidate, WindowState imeWindow, @NavigationBarPosition int navBarPosition) { // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME // window can be navigation color window. Loading @@ -2723,54 +2742,39 @@ public class DisplayPolicy { && navBarPosition == NAV_BAR_BOTTOM && (imeWindow.mAttrs.flags & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; if (opaque != null && opaqueOrDimming == opaque) { // If the top fullscreen-or-dimming window is also the top fullscreen, respect it // unless IME window is also eligible, since currently the IME window is always show // above the opaque fullscreen app window, regardless of the IME target window. // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed. return imeWindowCanNavColorWindow ? imeWindow : opaque; } if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) { // No dimming window is involved. Determine the result only with the IME window. return imeWindowCanNavColorWindow ? imeWindow : null; } if (!imeWindowCanNavColorWindow) { // No IME window is involved. Determine the result only with opaqueOrDimming. return opaqueOrDimming; // No IME window is involved. Determine the result only with candidate window. return candidate; } // The IME window and the dimming window are competing. Check if the dimming window can be // IME target or not. if (LayoutParams.mayUseInputMethod(opaqueOrDimming.mAttrs.flags)) { if (candidate != null && candidate.isDimming()) { // The IME window and the dimming window are competing. Check if the dimming window can // be IME target or not. if (LayoutParams.mayUseInputMethod(candidate.mAttrs.flags)) { // The IME window is above the dimming window. return imeWindow; } else { // The dimming window is above the IME window. return opaqueOrDimming; return candidate; } } return imeWindow; } @VisibleForTesting int updateLightNavigationBarLw(int appearance, WindowState opaque, WindowState opaqueOrDimming, WindowState imeWindow, WindowState navColorWin) { int updateLightNavigationBarLw(int appearance, WindowState navColorWin) { if (navColorWin == null || navColorWin.isDimming() || !isLightBarAllowed(navColorWin, ITYPE_NAVIGATION_BAR)) { // Clear the light flag while not allowed. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; return appearance; } if (navColorWin != null) { if (navColorWin == imeWindow || navColorWin == opaque) { // Respect the light flag. // Respect the light flag of navigation color window. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; appearance |= navColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_NAVIGATION_BARS; } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) { // Clear the light flag for dimming window. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } } if (!isLightBarAllowed(navColorWin, ITYPE_NAVIGATION_BAR)) { appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } return appearance; } Loading Loading @@ -2911,13 +2915,10 @@ public class DisplayPolicy { */ private int configureNavBarOpacity(int appearance, boolean multiWindowTaskVisible, boolean freeformRootTaskVisible) { final boolean fullscreenDrawsBackground = drawsBarBackground(mTopFullscreenOpaqueWindowState); final boolean dockedDrawsBackground = drawsBarBackground(mTopDockedOpaqueWindowState); final boolean drawBackground = drawsBarBackground(mNavBarBackgroundWindow); if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) { if (fullscreenDrawsBackground && dockedDrawsBackground) { if (drawBackground) { appearance = clearNavBarOpaqueFlag(appearance); } } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { Loading @@ -2925,7 +2926,7 @@ public class DisplayPolicy { if (mIsFreeformWindowOverlappingWithNavBar) { appearance = clearNavBarOpaqueFlag(appearance); } } else if (fullscreenDrawsBackground) { } else if (drawBackground) { appearance = clearNavBarOpaqueFlag(appearance); } } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { Loading @@ -2934,8 +2935,7 @@ public class DisplayPolicy { } } if (!isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState, TYPE_NAVIGATION_BAR) || !isFullyTransparentAllowed(mTopDockedOpaqueWindowState, TYPE_NAVIGATION_BAR)) { if (!isFullyTransparentAllowed(mNavBarBackgroundWindow, TYPE_NAVIGATION_BAR)) { appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; } Loading Loading @@ -3113,10 +3113,13 @@ public class DisplayPolicy { pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); pw.println(mTopFullscreenOpaqueOrDimmingWindowState); } if (mForcingShowNavBar) { pw.print(prefix); pw.print("mForcingShowNavBar="); pw.println(mForcingShowNavBar); pw.print(prefix); pw.print("mForcingShowNavBarLayer="); pw.println(mForcingShowNavBarLayer); if (mNavBarColorWindowCandidate != null) { pw.print(prefix); pw.print("mNavBarColorWindowCandidate="); pw.println(mNavBarColorWindowCandidate); } if (mNavBarBackgroundWindow != null) { pw.print(prefix); pw.print("mNavBarBackgroundWindow="); pw.println(mNavBarBackgroundWindow); } pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen); pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); Loading Loading @@ -3198,13 +3201,17 @@ public class DisplayPolicy { } @VisibleForTesting static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) { static boolean isOverlappingWithNavBar(@NonNull WindowState targetWindow, WindowState navBarWindow) { if (navBarWindow == null || !navBarWindow.isVisible() || targetWindow.mActivityRecord == null || !targetWindow.isVisible()) { return false; } return Rect.intersects(targetWindow.getFrame(), navBarWindow.getFrame()); // When the window is dimming means it's requesting dim layer to its host container, so // checking whether it's overlapping with navigation bar by its container's bounds. return Rect.intersects(targetWindow.isDimming() ? targetWindow.getBounds() : targetWindow.getFrame(), navBarWindow.getFrame()); } /** Loading services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +42 −67 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; import static com.android.server.wm.utils.WmDisplayCutout.NO_CUTOUT; import static org.junit.Assert.assertEquals; Loading Loading @@ -107,8 +106,7 @@ public class DisplayPolicyTests extends WindowTestsBase { @Test public void testChooseNavigationColorWindowLw() { final WindowState opaque = createOpaqueFullscreen(false); final WindowState candidate = createOpaqueFullscreen(false); final WindowState dimmingImTarget = createDimmingDialogWindow(true); final WindowState dimmingNonImTarget = createDimmingDialogWindow(false); Loading @@ -116,45 +114,51 @@ public class DisplayPolicyTests extends WindowTestsBase { final WindowState invisibleIme = createInputMethodWindow(false, true, false); final WindowState imeNonDrawNavBar = createInputMethodWindow(true, false, false); // If everything is null, return null // If everything is null, return null. assertNull(null, DisplayPolicy.chooseNavigationColorWindowLw( null, null, null, NAV_BAR_BOTTOM)); null, null, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, null, NAV_BAR_BOTTOM)); // If no IME windows, return candidate window. assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw( candidate, null, NAV_BAR_BOTTOM)); assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingImTarget, null, NAV_BAR_BOTTOM)); dimmingImTarget, null, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingNonImTarget, null, NAV_BAR_BOTTOM)); dimmingNonImTarget, null, NAV_BAR_BOTTOM)); assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( null, null, visibleIme, NAV_BAR_BOTTOM)); assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( null, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM)); // If IME is not visible, return candidate window. assertEquals(null, DisplayPolicy.chooseNavigationColorWindowLw( null, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw( candidate, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw( dimmingImTarget, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( null, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM)); dimmingNonImTarget, invisibleIme, NAV_BAR_BOTTOM)); // If IME is visible, return candidate when the candidate window is not dimming. assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, visibleIme, NAV_BAR_BOTTOM)); null, visibleIme, NAV_BAR_BOTTOM)); assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM)); candidate, visibleIme, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, visibleIme, NAV_BAR_RIGHT)); // If IME is visible and the candidate window is dimming, checks whether the dimming window // can be IME tartget or not. assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( dimmingImTarget, visibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM)); // Only IME windows that have FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS should be navigation color // window. assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(null, DisplayPolicy.chooseNavigationColorWindowLw( null, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw( candidate, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); dimmingImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); } @UseTestDisplay(addWindows = { W_NAVIGATION_BAR }) Loading Loading @@ -182,50 +186,21 @@ public class DisplayPolicyTests extends WindowTestsBase { // If there is no window, APPEARANCE_LIGHT_NAVIGATION_BARS is not allowed. assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, null, null, null, null)); // Opaque top fullscreen window overrides APPEARANCE_LIGHT_NAVIGATION_BARS flag. assertEquals(0, displayPolicy.updateLightNavigationBarLw( 0, opaqueDarkNavBar, opaqueDarkNavBar, null, opaqueDarkNavBar)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueDarkNavBar, opaqueDarkNavBar, null, opaqueDarkNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(0, opaqueLightNavBar, opaqueLightNavBar, null, opaqueLightNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, opaqueLightNavBar, null, opaqueLightNavBar)); displayPolicy.updateLightNavigationBarLw(APPEARANCE_LIGHT_NAVIGATION_BARS, null)); // Dimming window clears APPEARANCE_LIGHT_NAVIGATION_BARS. assertEquals(0, displayPolicy.updateLightNavigationBarLw(0, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( 0, opaqueDarkNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( 0, opaqueLightNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueDarkNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, dimming, imeDrawLightNavBar, dimming)); // IME window clears APPEARANCE_LIGHT_NAVIGATION_BARS assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, null, null, imeDrawDarkNavBar, imeDrawDarkNavBar)); APPEARANCE_LIGHT_NAVIGATION_BARS, dimming)); // Even if the top fullscreen has APPEARANCE_LIGHT_NAVIGATION_BARS, IME window wins. // Control window overrides APPEARANCE_LIGHT_NAVIGATION_BARS flag. assertEquals(0, displayPolicy.updateLightNavigationBarLw(0, opaqueDarkNavBar)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, opaqueLightNavBar, imeDrawDarkNavBar, imeDrawDarkNavBar)); // IME window should be able to use APPEARANCE_LIGHT_NAVIGATION_BARS. assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(0, opaqueDarkNavBar, opaqueDarkNavBar, imeDrawLightNavBar, imeDrawLightNavBar)); APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueDarkNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw( 0, opaqueLightNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar)); } @UseTestDisplay(addWindows = W_ACTIVITY) Loading Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +81 −74 Original line number Diff line number Diff line Loading @@ -315,6 +315,13 @@ public class DisplayPolicy { private WindowState mSystemUiControllingWindow; // Candidate window to determine the color of navigation bar. private WindowState mNavBarColorWindowCandidate; // The window to determine opacity and background of translucent navigation bar. The window // needs to be opaque. private WindowState mNavBarBackgroundWindow; private int mLastDisableFlags; private int mLastAppearance; private int mLastFullscreenAppearance; Loading Loading @@ -347,8 +354,6 @@ public class DisplayPolicy { private boolean mTopIsFullscreen; private boolean mForceStatusBar; private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; private boolean mForcingShowNavBar; private int mForcingShowNavBarLayer; private boolean mForceShowSystemBars; private boolean mShowingDream; Loading Loading @@ -1794,9 +1799,9 @@ public class DisplayPolicy { mTopFullscreenOpaqueOrDimmingWindowState = null; mTopDockedOpaqueWindowState = null; mTopDockedOpaqueOrDimmingWindowState = null; mNavBarColorWindowCandidate = null; mNavBarBackgroundWindow = null; mForceStatusBar = false; mForcingShowNavBar = false; mForcingShowNavBarLayer = -1; mAllowLockscreenWhenOn = false; mShowingDream = false; Loading @@ -1816,11 +1821,6 @@ public class DisplayPolicy { if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi); applyKeyguardPolicy(win, imeTarget); final int fl = attrs.flags; if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi && attrs.type == TYPE_INPUT_METHOD) { mForcingShowNavBar = true; mForcingShowNavBarLayer = win.getSurfaceLayer(); } boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type < FIRST_SYSTEM_WINDOW; Loading Loading @@ -1891,12 +1891,35 @@ public class DisplayPolicy { } } // Check if the freeform window overlaps with the navigation bar area. final WindowState navBarWin = hasNavigationBar() ? mNavigationBar : null; if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode() && isOverlappingWithNavBar(win, navBarWin)) { if (isOverlappingWithNavBar(win, navBarWin)) { // Check if the freeform window overlaps with the navigation bar area. if (!mIsFreeformWindowOverlappingWithNavBar && win.inFreeformWindowingMode()) { mIsFreeformWindowOverlappingWithNavBar = true; } // Cache app window that overlaps with the navigation bar area to determine opacity and // appearance of the navigation bar. We only need to cache one window because there // should be only one overlapping window if it's not in gesture navigation mode; if it's // in gesture navigation mode, the navigation bar will be NAV_BAR_FORCE_TRANSPARENT and // its appearance won't be decided by overlapping windows. if (affectsSystemUi) { if ((appWindow && attached == null && attrs.isFullscreen()) || attrs.type == TYPE_VOICE_INTERACTION) { if (mNavBarColorWindowCandidate == null) { mNavBarColorWindowCandidate = win; } if (mNavBarBackgroundWindow == null) { mNavBarBackgroundWindow = win; } } else if (win.isDimming()) { // For dimming window with it's host bounds overlapping with navigation bar, it // can be used to determine navigation bar's color but not opacity. if (mNavBarColorWindowCandidate == null) { mNavBarColorWindowCandidate = win; } } } } // Also keep track of any windows that are dimming but not necessarily fullscreen in the // docked root task. Loading Loading @@ -2646,15 +2669,12 @@ public class DisplayPolicy { mTopDockedOpaqueOrDimmingWindowState); final int disableFlags = win.getDisableFlags(); final int opaqueAppearance = updateSystemBarsLw(win, disableFlags); final WindowState navColorWin = chooseNavigationColorWindowLw( mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState, final WindowState navColorWin = chooseNavigationColorWindowLw(mNavBarColorWindowCandidate, mDisplayContent.mInputMethodWindow, mNavigationBarPosition); final boolean isNavbarColorManagedByIme = navColorWin != null && navColorWin == mDisplayContent.mInputMethodWindow; final int appearance = updateLightNavigationBarLw( win.mAttrs.insetsFlags.appearance, mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState, mDisplayContent.mInputMethodWindow, navColorWin) | opaqueAppearance; final int appearance = updateLightNavigationBarLw(win.mAttrs.insetsFlags.appearance, navColorWin) | opaqueAppearance; final int behavior = win.mAttrs.insetsFlags.behavior; final boolean isFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR) || !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR); Loading Loading @@ -2713,8 +2733,7 @@ public class DisplayPolicy { @VisibleForTesting @Nullable static WindowState chooseNavigationColorWindowLw(WindowState opaque, WindowState opaqueOrDimming, WindowState imeWindow, static WindowState chooseNavigationColorWindowLw(WindowState candidate, WindowState imeWindow, @NavigationBarPosition int navBarPosition) { // If the IME window is visible and FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS is set, then IME // window can be navigation color window. Loading @@ -2723,54 +2742,39 @@ public class DisplayPolicy { && navBarPosition == NAV_BAR_BOTTOM && (imeWindow.mAttrs.flags & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; if (opaque != null && opaqueOrDimming == opaque) { // If the top fullscreen-or-dimming window is also the top fullscreen, respect it // unless IME window is also eligible, since currently the IME window is always show // above the opaque fullscreen app window, regardless of the IME target window. // TODO(b/31559891): Maybe we need to revisit this condition once b/31559891 is fixed. return imeWindowCanNavColorWindow ? imeWindow : opaque; } if (opaqueOrDimming == null || !opaqueOrDimming.isDimming()) { // No dimming window is involved. Determine the result only with the IME window. return imeWindowCanNavColorWindow ? imeWindow : null; } if (!imeWindowCanNavColorWindow) { // No IME window is involved. Determine the result only with opaqueOrDimming. return opaqueOrDimming; // No IME window is involved. Determine the result only with candidate window. return candidate; } // The IME window and the dimming window are competing. Check if the dimming window can be // IME target or not. if (LayoutParams.mayUseInputMethod(opaqueOrDimming.mAttrs.flags)) { if (candidate != null && candidate.isDimming()) { // The IME window and the dimming window are competing. Check if the dimming window can // be IME target or not. if (LayoutParams.mayUseInputMethod(candidate.mAttrs.flags)) { // The IME window is above the dimming window. return imeWindow; } else { // The dimming window is above the IME window. return opaqueOrDimming; return candidate; } } return imeWindow; } @VisibleForTesting int updateLightNavigationBarLw(int appearance, WindowState opaque, WindowState opaqueOrDimming, WindowState imeWindow, WindowState navColorWin) { int updateLightNavigationBarLw(int appearance, WindowState navColorWin) { if (navColorWin == null || navColorWin.isDimming() || !isLightBarAllowed(navColorWin, ITYPE_NAVIGATION_BAR)) { // Clear the light flag while not allowed. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; return appearance; } if (navColorWin != null) { if (navColorWin == imeWindow || navColorWin == opaque) { // Respect the light flag. // Respect the light flag of navigation color window. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; appearance |= navColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_NAVIGATION_BARS; } else if (navColorWin == opaqueOrDimming && navColorWin.isDimming()) { // Clear the light flag for dimming window. appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } } if (!isLightBarAllowed(navColorWin, ITYPE_NAVIGATION_BAR)) { appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS; } return appearance; } Loading Loading @@ -2911,13 +2915,10 @@ public class DisplayPolicy { */ private int configureNavBarOpacity(int appearance, boolean multiWindowTaskVisible, boolean freeformRootTaskVisible) { final boolean fullscreenDrawsBackground = drawsBarBackground(mTopFullscreenOpaqueWindowState); final boolean dockedDrawsBackground = drawsBarBackground(mTopDockedOpaqueWindowState); final boolean drawBackground = drawsBarBackground(mNavBarBackgroundWindow); if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) { if (fullscreenDrawsBackground && dockedDrawsBackground) { if (drawBackground) { appearance = clearNavBarOpaqueFlag(appearance); } } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { Loading @@ -2925,7 +2926,7 @@ public class DisplayPolicy { if (mIsFreeformWindowOverlappingWithNavBar) { appearance = clearNavBarOpaqueFlag(appearance); } } else if (fullscreenDrawsBackground) { } else if (drawBackground) { appearance = clearNavBarOpaqueFlag(appearance); } } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { Loading @@ -2934,8 +2935,7 @@ public class DisplayPolicy { } } if (!isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState, TYPE_NAVIGATION_BAR) || !isFullyTransparentAllowed(mTopDockedOpaqueWindowState, TYPE_NAVIGATION_BAR)) { if (!isFullyTransparentAllowed(mNavBarBackgroundWindow, TYPE_NAVIGATION_BAR)) { appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; } Loading Loading @@ -3113,10 +3113,13 @@ public class DisplayPolicy { pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); pw.println(mTopFullscreenOpaqueOrDimmingWindowState); } if (mForcingShowNavBar) { pw.print(prefix); pw.print("mForcingShowNavBar="); pw.println(mForcingShowNavBar); pw.print(prefix); pw.print("mForcingShowNavBarLayer="); pw.println(mForcingShowNavBarLayer); if (mNavBarColorWindowCandidate != null) { pw.print(prefix); pw.print("mNavBarColorWindowCandidate="); pw.println(mNavBarColorWindowCandidate); } if (mNavBarBackgroundWindow != null) { pw.print(prefix); pw.print("mNavBarBackgroundWindow="); pw.println(mNavBarBackgroundWindow); } pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen); pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); Loading Loading @@ -3198,13 +3201,17 @@ public class DisplayPolicy { } @VisibleForTesting static boolean isOverlappingWithNavBar(WindowState targetWindow, WindowState navBarWindow) { static boolean isOverlappingWithNavBar(@NonNull WindowState targetWindow, WindowState navBarWindow) { if (navBarWindow == null || !navBarWindow.isVisible() || targetWindow.mActivityRecord == null || !targetWindow.isVisible()) { return false; } return Rect.intersects(targetWindow.getFrame(), navBarWindow.getFrame()); // When the window is dimming means it's requesting dim layer to its host container, so // checking whether it's overlapping with navigation bar by its container's bounds. return Rect.intersects(targetWindow.isDimming() ? targetWindow.getBounds() : targetWindow.getFrame(), navBarWindow.getFrame()); } /** Loading
services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +42 −67 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; import static com.android.server.wm.utils.WmDisplayCutout.NO_CUTOUT; import static org.junit.Assert.assertEquals; Loading Loading @@ -107,8 +106,7 @@ public class DisplayPolicyTests extends WindowTestsBase { @Test public void testChooseNavigationColorWindowLw() { final WindowState opaque = createOpaqueFullscreen(false); final WindowState candidate = createOpaqueFullscreen(false); final WindowState dimmingImTarget = createDimmingDialogWindow(true); final WindowState dimmingNonImTarget = createDimmingDialogWindow(false); Loading @@ -116,45 +114,51 @@ public class DisplayPolicyTests extends WindowTestsBase { final WindowState invisibleIme = createInputMethodWindow(false, true, false); final WindowState imeNonDrawNavBar = createInputMethodWindow(true, false, false); // If everything is null, return null // If everything is null, return null. assertNull(null, DisplayPolicy.chooseNavigationColorWindowLw( null, null, null, NAV_BAR_BOTTOM)); null, null, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, null, NAV_BAR_BOTTOM)); // If no IME windows, return candidate window. assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw( candidate, null, NAV_BAR_BOTTOM)); assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingImTarget, null, NAV_BAR_BOTTOM)); dimmingImTarget, null, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingNonImTarget, null, NAV_BAR_BOTTOM)); dimmingNonImTarget, null, NAV_BAR_BOTTOM)); assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( null, null, visibleIme, NAV_BAR_BOTTOM)); assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( null, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM)); // If IME is not visible, return candidate window. assertEquals(null, DisplayPolicy.chooseNavigationColorWindowLw( null, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw( candidate, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw( dimmingImTarget, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( null, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM)); dimmingNonImTarget, invisibleIme, NAV_BAR_BOTTOM)); // If IME is visible, return candidate when the candidate window is not dimming. assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, visibleIme, NAV_BAR_BOTTOM)); null, visibleIme, NAV_BAR_BOTTOM)); assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingImTarget, visibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM)); candidate, visibleIme, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, invisibleIme, NAV_BAR_BOTTOM)); assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, visibleIme, NAV_BAR_RIGHT)); // If IME is visible and the candidate window is dimming, checks whether the dimming window // can be IME tartget or not. assertEquals(visibleIme, DisplayPolicy.chooseNavigationColorWindowLw( dimmingImTarget, visibleIme, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( dimmingNonImTarget, visibleIme, NAV_BAR_BOTTOM)); // Only IME windows that have FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS should be navigation color // window. assertEquals(opaque, DisplayPolicy.chooseNavigationColorWindowLw( opaque, opaque, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(null, DisplayPolicy.chooseNavigationColorWindowLw( null, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(candidate, DisplayPolicy.chooseNavigationColorWindowLw( candidate, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(dimmingImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); dimmingImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); assertEquals(dimmingNonImTarget, DisplayPolicy.chooseNavigationColorWindowLw( opaque, dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); dimmingNonImTarget, imeNonDrawNavBar, NAV_BAR_BOTTOM)); } @UseTestDisplay(addWindows = { W_NAVIGATION_BAR }) Loading Loading @@ -182,50 +186,21 @@ public class DisplayPolicyTests extends WindowTestsBase { // If there is no window, APPEARANCE_LIGHT_NAVIGATION_BARS is not allowed. assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, null, null, null, null)); // Opaque top fullscreen window overrides APPEARANCE_LIGHT_NAVIGATION_BARS flag. assertEquals(0, displayPolicy.updateLightNavigationBarLw( 0, opaqueDarkNavBar, opaqueDarkNavBar, null, opaqueDarkNavBar)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueDarkNavBar, opaqueDarkNavBar, null, opaqueDarkNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(0, opaqueLightNavBar, opaqueLightNavBar, null, opaqueLightNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, opaqueLightNavBar, null, opaqueLightNavBar)); displayPolicy.updateLightNavigationBarLw(APPEARANCE_LIGHT_NAVIGATION_BARS, null)); // Dimming window clears APPEARANCE_LIGHT_NAVIGATION_BARS. assertEquals(0, displayPolicy.updateLightNavigationBarLw(0, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( 0, opaqueDarkNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( 0, opaqueLightNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueDarkNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, dimming, null, dimming)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, dimming, imeDrawLightNavBar, dimming)); // IME window clears APPEARANCE_LIGHT_NAVIGATION_BARS assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, null, null, imeDrawDarkNavBar, imeDrawDarkNavBar)); APPEARANCE_LIGHT_NAVIGATION_BARS, dimming)); // Even if the top fullscreen has APPEARANCE_LIGHT_NAVIGATION_BARS, IME window wins. // Control window overrides APPEARANCE_LIGHT_NAVIGATION_BARS flag. assertEquals(0, displayPolicy.updateLightNavigationBarLw(0, opaqueDarkNavBar)); assertEquals(0, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar, opaqueLightNavBar, imeDrawDarkNavBar, imeDrawDarkNavBar)); // IME window should be able to use APPEARANCE_LIGHT_NAVIGATION_BARS. assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw(0, opaqueDarkNavBar, opaqueDarkNavBar, imeDrawLightNavBar, imeDrawLightNavBar)); APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueDarkNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw( 0, opaqueLightNavBar)); assertEquals(APPEARANCE_LIGHT_NAVIGATION_BARS, displayPolicy.updateLightNavigationBarLw( APPEARANCE_LIGHT_NAVIGATION_BARS, opaqueLightNavBar)); } @UseTestDisplay(addWindows = W_ACTIVITY) Loading