Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4649141 authored by Jerry Chang's avatar Jerry Chang Committed by Automerger Merge Worker
Browse files

Merge "Make system bars appearence logic more generic (2/N)" into sc-v2-dev...

Merge "Make system bars appearence logic more generic (2/N)" into sc-v2-dev am: f612f5ed am: eba8ce21

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15073690

Change-Id: I33021bb547d6c1b676c935811e50e2dba9c812dc
parents cde14e97 eba8ce21
Loading
Loading
Loading
Loading
+81 −74
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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.
@@ -2649,15 +2672,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);
@@ -2716,8 +2736,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.
@@ -2726,54 +2745,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;
    }

@@ -2914,13 +2918,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) {
@@ -2928,7 +2929,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) {
@@ -2937,8 +2938,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;
        }

@@ -3116,10 +3116,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);
@@ -3201,13 +3204,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());
    }

    /**
+42 −67
Original line number Diff line number Diff line
@@ -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;
@@ -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);

@@ -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 })
@@ -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)