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

Commit 38eacbf7 authored by Jerry Chang's avatar Jerry Chang Committed by Android (Google) Code Review
Browse files

Merge changes from topic "b/179251684" into sc-v2-dev

* changes:
  Make system bars appearence logic more generic (2/N)
  Make system bars appearence logic more generic (1/N)
parents b6bfa268 ed389f0c
Loading
Loading
Loading
Loading
+65 −96
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
@@ -313,6 +314,7 @@ public class DisplayPolicy {
    private WindowState mLastFocusedWindow;

    private WindowState mSystemUiControllingWindow;
    private WindowState mNavBarColorWindowCandidate;

    private int mLastDisableFlags;
    private int mLastAppearance;
@@ -346,8 +348,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;
@@ -1416,7 +1416,7 @@ public class DisplayPolicy {
    /**
     * @return true if the system bars are forced to stay visible
     */
    public boolean areSystemBarsForcedShownLw(WindowState windowState) {
    public boolean areSystemBarsForcedShownLw() {
        return mForceShowSystemBars;
    }

@@ -1793,9 +1793,8 @@ public class DisplayPolicy {
        mTopFullscreenOpaqueOrDimmingWindowState = null;
        mTopDockedOpaqueWindowState = null;
        mTopDockedOpaqueOrDimmingWindowState = null;
        mNavBarColorWindowCandidate = null;
        mForceStatusBar = false;
        mForcingShowNavBar = false;
        mForcingShowNavBarLayer = -1;

        mAllowLockscreenWhenOn = false;
        mShowingDream = false;
@@ -1815,11 +1814,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;
@@ -1890,12 +1884,25 @@ 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 (mNavBarColorWindowCandidate == null && affectsSystemUi) {
                if ((appWindow && attached == null && attrs.isFullscreen())
                        || attrs.type == TYPE_VOICE_INTERACTION
                        || win.isDimming()) {
                    mNavBarColorWindowCandidate = win;
                }
            }
        }

        // Also keep track of any windows that are dimming but not necessarily fullscreen in the
        // docked root task.
@@ -2628,8 +2635,6 @@ public class DisplayPolicy {
        final WindowState win = winCandidate;
        mSystemUiControllingWindow = win;

        mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);

        final boolean inSplitScreen =
                mService.mRoot.getDefaultTaskDisplayArea().isSplitScreenModeActivated();
        if (inSplitScreen) {
@@ -2647,15 +2652,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);
@@ -2714,8 +2716,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.
@@ -2724,49 +2725,37 @@ 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;
            }
        }

    @VisibleForTesting
    int updateLightNavigationBarLw(int appearance, WindowState opaque,
            WindowState opaqueOrDimming, WindowState imeWindow, WindowState navColorWin) {
        return imeWindow;
    }

    @VisibleForTesting
    int updateLightNavigationBarLw(int appearance, WindowState navColorWin) {
        if (navColorWin != null) {
            if (navColorWin == imeWindow || navColorWin == opaque) {
            if (navColorWin.isDimming()) {
                // Clear the light flag for dimming window.
                appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
            } else {
                // Respect the light flag.
                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)) {
@@ -2776,19 +2765,22 @@ public class DisplayPolicy {
    }

    private int updateSystemBarsLw(WindowState win, int disableFlags) {
        final boolean dockedRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
                .isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();

        // We need to force system bars when the docked root task is visible, when the freeform
        // root task is focused but also when we are resizing for the transitions when docked
        // root task visibility changes.
        mForceShowSystemBars = dockedRootTaskVisible || win.inFreeformWindowingMode() || resizing;
        final TaskDisplayArea defaultTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
        final boolean multiWindowTaskVisible =
                defaultTaskDisplayArea.isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
                        || defaultTaskDisplayArea.isRootTaskVisible(WINDOWING_MODE_MULTI_WINDOW);
        final boolean freeformRootTaskVisible =
                defaultTaskDisplayArea.isRootTaskVisible(WINDOWING_MODE_FREEFORM);

        // We need to force shows system bars when the multi-window or freeform root task is
        // visible.
        mForceShowSystemBars = multiWindowTaskVisible || freeformRootTaskVisible;
        mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);

        int appearance = APPEARANCE_OPAQUE_NAVIGATION_BARS | APPEARANCE_OPAQUE_STATUS_BARS;

        appearance = configureStatusBarOpacity(appearance);
        appearance = configureNavBarOpacity(appearance, dockedRootTaskVisible, resizing);
        appearance = configureNavBarOpacity(appearance, multiWindowTaskVisible,
                freeformRootTaskVisible);

        final boolean requestHideNavBar = !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
        final long now = SystemClock.uptimeMillis();
@@ -2907,53 +2899,35 @@ public class DisplayPolicy {
     * @return the current visibility flags with the nav-bar opacity related flags toggled based
     *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
     */
    private int configureNavBarOpacity(int appearance, boolean dockedRootTaskVisible,
            boolean isDockedDividerResizing) {
        final boolean freeformRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
                .isRootTaskVisible(WINDOWING_MODE_FREEFORM);
        final boolean fullscreenDrawsBackground =
                drawsBarBackground(mTopFullscreenOpaqueWindowState);
        final boolean dockedDrawsBackground =
                drawsBarBackground(mTopDockedOpaqueWindowState);
    private int configureNavBarOpacity(int appearance, boolean multiWindowTaskVisible,
            boolean freeformRootTaskVisible) {
        final boolean drawBackground = drawsBarBackground(mNavBarColorWindowCandidate);

        if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
            if (fullscreenDrawsBackground && dockedDrawsBackground) {
            if (drawBackground) {
                appearance = clearNavBarOpaqueFlag(appearance);
            } else if (dockedRootTaskVisible) {
                appearance = setNavBarOpaqueFlag(appearance);
            }
        } else if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
            if (dockedRootTaskVisible || freeformRootTaskVisible || isDockedDividerResizing) {
            if (multiWindowTaskVisible || freeformRootTaskVisible) {
                if (mIsFreeformWindowOverlappingWithNavBar) {
                    appearance = clearNavBarOpaqueFlag(appearance);
                } else {
                    appearance = setNavBarOpaqueFlag(appearance);
                }
            } else if (fullscreenDrawsBackground) {
            } else if (drawBackground) {
                appearance = clearNavBarOpaqueFlag(appearance);
            }
        } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
            if (isDockedDividerResizing) {
                appearance = setNavBarOpaqueFlag(appearance);
            } else if (freeformRootTaskVisible) {
            if (freeformRootTaskVisible) {
                appearance = clearNavBarOpaqueFlag(appearance);
            } else {
                appearance = setNavBarOpaqueFlag(appearance);
            }
        }

        if (!isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState, TYPE_NAVIGATION_BAR)
                || !isFullyTransparentAllowed(mTopDockedOpaqueWindowState, TYPE_NAVIGATION_BAR)) {
        if (!isFullyTransparentAllowed(mNavBarColorWindowCandidate, TYPE_NAVIGATION_BAR)) {
            appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
        }

        return appearance;
    }

    private int setNavBarOpaqueFlag(int appearance) {
        return appearance | APPEARANCE_OPAQUE_NAVIGATION_BARS;
    }

    private int clearNavBarOpaqueFlag(int appearance) {
        return appearance & ~APPEARANCE_OPAQUE_NAVIGATION_BARS;
    }
@@ -3125,11 +3099,6 @@ 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);
        }
        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
        pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
        pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
+10 −32
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ package com.android.server.wm;

import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsController.LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
@@ -135,11 +133,8 @@ class InsetsPolicy {
            abortTransient();
        }
        mFocusedWin = focusedWin;
        boolean forceShowsSystemBarsForWindowingMode = forceShowsSystemBarsForWindowingMode();
        InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin,
                forceShowsSystemBarsForWindowingMode);
        InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin,
                forceShowsSystemBarsForWindowingMode);
        InsetsControlTarget statusControlTarget = getStatusControlTarget(focusedWin);
        InsetsControlTarget navControlTarget = getNavControlTarget(focusedWin);
        mStateController.onBarControlTargetChanged(statusControlTarget,
                getFakeControlTarget(focusedWin, statusControlTarget),
                navControlTarget,
@@ -304,8 +299,7 @@ class InsetsPolicy {
        return realControlTarget == mDummyControlTarget ? focused : null;
    }

    private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin,
            boolean forceShowsSystemBarsForWindowingMode) {
    private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin) {
        if (mShowingTransientTypes.indexOf(ITYPE_STATUS_BAR) != -1) {
            return mDummyControlTarget;
        }
@@ -319,10 +313,9 @@ class InsetsPolicy {
                    focusedWin.mAttrs.packageName);
            return mDisplayContent.mRemoteInsetsControlTarget;
        }
        if (forceShowsSystemBarsForWindowingMode) {
            // Status bar is forcibly shown for the windowing mode which is a steady state.
            // We don't want the client to control the status bar, and we will dispatch the real
            // visibility of status bar to the client.
        if (mPolicy.areSystemBarsForcedShownLw()) {
            // Status bar is forcibly shown, we don't want the client to control the status bar, and
            // we will dispatch the real visibility of status bar to the client.
            return null;
        }
        if (forceShowsStatusBarTransiently()) {
@@ -350,8 +343,7 @@ class InsetsPolicy {
                && !win.inMultiWindowMode();
    }

    private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin,
            boolean forceShowsSystemBarsForWindowingMode) {
    private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin) {
        final WindowState imeWin = mDisplayContent.mInputMethodWindow;
        if (imeWin != null && imeWin.isVisible()) {
            // Force showing navigation bar while IME is visible.
@@ -369,10 +361,9 @@ class InsetsPolicy {
                    focusedWin.mAttrs.packageName);
            return mDisplayContent.mRemoteInsetsControlTarget;
        }
        if (forceShowsSystemBarsForWindowingMode) {
            // Navigation bar is forcibly shown for the windowing mode which is a steady state.
            // We don't want the client to control the navigation bar, and we will dispatch the real
            // visibility of navigation bar to the client.
        if (mPolicy.areSystemBarsForcedShownLw()) {
            // Navigation bar is forcibly shown, we don't want the client to control the navigation
            // bar, and we will dispatch the real visibility of navigation bar to the client.
            return null;
        }
        if (forceShowsNavigationBarTransiently()) {
@@ -417,19 +408,6 @@ class InsetsPolicy {
                && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
    }

    private boolean forceShowsSystemBarsForWindowingMode() {
        final boolean isDockedRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
                .isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
        final boolean isFreeformRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
                .isRootTaskVisible(WINDOWING_MODE_FREEFORM);
        final boolean isResizing = mDisplayContent.getDockedDividerController().isResizing();

        // We need to force system bars when the docked root task is visible, when the freeform
        // root task is visible but also when we are resizing for the transitions when docked
        // root task visibility changes.
        return isDockedRootTaskVisible || isFreeformRootTaskVisible || isResizing;
    }

    @VisibleForTesting
    void startAnimation(boolean show, Runnable callback) {
        int typesReady = 0;
+1 −1
Original line number Diff line number Diff line
@@ -2469,7 +2469,7 @@ public class WindowManagerService extends IWindowManager.Stub
            if (win.mActivityRecord != null) {
                win.mActivityRecord.updateReportedVisibilityLocked();
            }
            if (displayPolicy.areSystemBarsForcedShownLw(win)) {
            if (displayPolicy.areSystemBarsForcedShownLw()) {
                result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
            }
            if (!win.isGoneForLayout()) {
+1 −1
Original line number Diff line number Diff line
@@ -3892,7 +3892,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        final boolean forceRelayout = syncRedraw || reportOrientation || isDragResizeChanged();
        final DisplayContent displayContent = getDisplayContent();
        final boolean alwaysConsumeSystemBars =
                displayContent.getDisplayPolicy().areSystemBarsForcedShownLw(this);
                displayContent.getDisplayPolicy().areSystemBarsForcedShownLw();
        final int displayId = displayContent.getDisplayId();

        markRedrawForSyncReported();
+42 −67

File changed.

Preview size limit exceeded, changes collapsed.

Loading