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

Commit 46b4e36c authored by Tiger Huang's avatar Tiger Huang Committed by Automerger Merge Worker
Browse files

Merge "Remove BarController" into sc-dev am: 971df2cc

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

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I69b6c69f7b120428222ae9a6679c132e57cfd6de
parents a47772b9 971df2cc
Loading
Loading
Loading
Loading
+0 −70
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import android.annotation.NonNull;
import android.graphics.Rect;

/**
 * Controls state/behavior specific to a system bar window.
 */
public class BarController {
    private final int mWindowType;

    private final Rect mContentFrame = new Rect();

    BarController(int windowType) {
        mWindowType = windowType;
    }

    /**
     * Sets the frame within which the bar will display its content.
     *
     * This is used to determine if letterboxes interfere with the display of such content.
     */
    void setContentFrame(Rect frame) {
        mContentFrame.set(frame);
    }

    private Rect getContentFrame(@NonNull WindowState win) {
        final Rect rotatedContentFrame = win.mToken.getFixedRotationBarContentFrame(mWindowType);
        return rotatedContentFrame != null ? rotatedContentFrame : mContentFrame;
    }

    boolean isLightAppearanceAllowed(WindowState win) {
        if (win == null) {
            return true;
        }
        return !win.isLetterboxedOverlappingWith(getContentFrame(win));
    }

    /**
     * @return {@code true} if bar is allowed to be fully transparent when given window is show.
     *
     * <p>Prevents showing a transparent bar over a letterboxed activity which can make
     * notification icons or navigation buttons unreadable due to contrast between letterbox
     * background and an activity. For instance, this happens when letterbox background is solid
     * black while activity is white. To resolve this, only semi-transparent bars are allowed to
     * be drawn over letterboxed activity.
     */
    boolean isFullyTransparentAllowed(WindowState win) {
        if (win == null) {
            return true;
        }
        return win.isFullyTransparentBarAllowed(getContentFrame(win));
    }
}
+55 −49
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ import static android.view.WindowManagerPolicyConstants.ALT_BAR_TOP;
import static android.view.WindowManagerPolicyConstants.ALT_BAR_UNKNOWN;
import static android.view.WindowManagerPolicyConstants.EXTRA_HDMI_PLUGGED_STATE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;

@@ -305,8 +306,7 @@ public class DisplayPolicy {

    private boolean mLastImmersiveMode;

    private final BarController mStatusBarController;
    private final BarController mNavigationBarController;
    private final SparseArray<Rect> mBarContentFrames = new SparseArray<>();

    // The windows we were told about in focusChanged.
    private WindowState mFocusedWindow;
@@ -432,8 +432,8 @@ public class DisplayPolicy {

        final int displayId = displayContent.getDisplayId();

        mStatusBarController = new BarController(TYPE_STATUS_BAR);
        mNavigationBarController = new BarController(TYPE_NAVIGATION_BAR);
        mBarContentFrames.put(TYPE_STATUS_BAR, new Rect());
        mBarContentFrames.put(TYPE_NAVIGATION_BAR, new Rect());

        final Resources r = mContext.getResources();
        mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
@@ -1253,11 +1253,6 @@ public class DisplayPolicy {
                displayFrames.mDisplayCutoutSafe.top);
    }

    @VisibleForTesting
    BarController getStatusBarController() {
        return mStatusBarController;
    }

    WindowState getStatusBar() {
        return mStatusBar != null ? mStatusBar : mStatusBarAlt;
    }
@@ -1473,7 +1468,7 @@ public class DisplayPolicy {
        mSystemGestures.screenHeight = info.logicalHeight;
    }

    private void layoutStatusBar(DisplayFrames displayFrames, Rect simulatedContentFrame) {
    private void layoutStatusBar(DisplayFrames displayFrames, Rect contentFrame) {
        // decide where the status bar goes ahead of time
        if (mStatusBar == null) {
            return;
@@ -1500,21 +1495,16 @@ public class DisplayPolicy {
                    statusBarBottom);
        }

        // Tell the bar controller where the collapsed status bar content is.
        sTmpRect.set(windowFrames.mFrame);
        sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
        sTmpRect.top = windowFrames.mFrame.top; // Ignore top display cutout inset
        sTmpRect.bottom = statusBarBottom; // Use collapsed status bar size
        if (simulatedContentFrame != null) {
            simulatedContentFrame.set(sTmpRect);
        } else {
            mStatusBarController.setContentFrame(sTmpRect);
        }
        contentFrame.set(sTmpRect);
    }

    private void layoutNavigationBar(DisplayFrames displayFrames, Rect simulatedContentFrame) {
    private int layoutNavigationBar(DisplayFrames displayFrames, Rect contentFrame) {
        if (mNavigationBar == null) {
            return;
            return NAV_BAR_INVALID;
        }

        final int uiMode = mDisplayContent.getConfiguration().uiMode;
@@ -1552,17 +1542,12 @@ public class DisplayPolicy {
        windowFrames.setFrames(navigationFrame /* parentFrame */,
                navigationFrame /* displayFrame */);
        mNavigationBar.computeFrameAndUpdateSourceFrame();
        final Rect contentFrame =  sTmpRect;
        contentFrame.set(windowFrames.mFrame);
        contentFrame.intersect(displayFrames.mDisplayCutoutSafe);
        if (simulatedContentFrame != null) {
            simulatedContentFrame.set(contentFrame);
        } else {
            mNavigationBarPosition = navBarPosition;
            mNavigationBarController.setContentFrame(contentFrame);
        }
        sTmpRect.set(windowFrames.mFrame);
        sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
        contentFrame.set(sTmpRect);

        if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame);
        return navBarPosition;
    }

    private boolean canReceiveInput(WindowState win) {
@@ -1609,11 +1594,12 @@ public class DisplayPolicy {
     */
    public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
        if (win == mNavigationBar) {
            layoutNavigationBar(displayFrames, null /* simulatedContentFrame */);
            mNavigationBarPosition = layoutNavigationBar(displayFrames,
                    mBarContentFrames.get(TYPE_NAVIGATION_BAR));
            return;
        }
        if ((win == mStatusBar && !canReceiveInput(win))) {
            layoutStatusBar(displayFrames, null /* simulatedContentFrame */);
            layoutStatusBar(displayFrames, mBarContentFrames.get(TYPE_STATUS_BAR));
            return;
        }
        final WindowManager.LayoutParams attrs = win.getAttrs();
@@ -2622,7 +2608,7 @@ public class DisplayPolicy {
                // Otherwise if it's dimming, clear the light flag.
                appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
            }
            if (!mStatusBarController.isLightAppearanceAllowed(statusColorWin)) {
            if (!isLightBarAllowed(statusColorWin, TYPE_STATUS_BAR)) {
                appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
            }
        }
@@ -2685,7 +2671,7 @@ public class DisplayPolicy {
                // Clear the light flag for dimming window.
                appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
            }
            if (!mNavigationBarController.isLightAppearanceAllowed(navColorWin)) {
            if (!isLightBarAllowed(navColorWin, TYPE_NAVIGATION_BAR)) {
                appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
            }
        }
@@ -2739,7 +2725,36 @@ public class DisplayPolicy {
        return appearance;
    }

    private boolean drawsBarBackground(WindowState win, BarController controller) {
    private boolean isLightBarAllowed(WindowState win, int windowType) {
        if (win == null) {
            return true;
        }
        return !win.isLetterboxedOverlappingWith(getBarContentFrameForWindow(win, windowType));
    }

    private Rect getBarContentFrameForWindow(WindowState win, int windowType) {
        final Rect rotatedBarFrame = win.mToken.getFixedRotationBarContentFrame(windowType);
        return rotatedBarFrame != null ? rotatedBarFrame : mBarContentFrames.get(windowType);
    }

    /**
     * @return {@code true} if bar is allowed to be fully transparent when given window is show.
     *
     * <p>Prevents showing a transparent bar over a letterboxed activity which can make
     * notification icons or navigation buttons unreadable due to contrast between letterbox
     * background and an activity. For instance, this happens when letterbox background is solid
     * black while activity is white. To resolve this, only semi-transparent bars are allowed to
     * be drawn over letterboxed activity.
     */
    @VisibleForTesting
    boolean isFullyTransparentAllowed(WindowState win, int windowType) {
        if (win == null) {
            return true;
        }
        return win.isFullyTransparentBarAllowed(getBarContentFrameForWindow(win, windowType));
    }

    private boolean drawsBarBackground(WindowState win) {
        if (win == null) {
            return true;
        }
@@ -2752,27 +2767,19 @@ public class DisplayPolicy {
        return forceDrawsSystemBars || drawsSystemBars;
    }

    private boolean drawsStatusBarBackground(WindowState win) {
        return drawsBarBackground(win, mStatusBarController);
    }

    private boolean drawsNavigationBarBackground(WindowState win) {
        return drawsBarBackground(win, mNavigationBarController);
    }

    /** @return the current visibility flags with the status bar opacity related flags toggled. */
    private int configureStatusBarOpacity(int appearance) {
        final boolean fullscreenDrawsBackground =
                drawsStatusBarBackground(mTopFullscreenOpaqueWindowState);
                drawsBarBackground(mTopFullscreenOpaqueWindowState);
        final boolean dockedDrawsBackground =
                drawsStatusBarBackground(mTopDockedOpaqueWindowState);
                drawsBarBackground(mTopDockedOpaqueWindowState);

        if (fullscreenDrawsBackground && dockedDrawsBackground) {
            appearance &= ~APPEARANCE_OPAQUE_STATUS_BARS;
        }

        if (!mStatusBarController.isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState)
                || !mStatusBarController.isFullyTransparentAllowed(mTopDockedOpaqueWindowState)) {
        if (!isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState, TYPE_STATUS_BAR)
                || !isFullyTransparentAllowed(mTopDockedOpaqueWindowState, TYPE_STATUS_BAR)) {
            appearance |= APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
        }

@@ -2788,9 +2795,9 @@ public class DisplayPolicy {
        final boolean freeformRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
                .isRootTaskVisible(WINDOWING_MODE_FREEFORM);
        final boolean fullscreenDrawsBackground =
                drawsNavigationBarBackground(mTopFullscreenOpaqueWindowState);
                drawsBarBackground(mTopFullscreenOpaqueWindowState);
        final boolean dockedDrawsBackground =
                drawsNavigationBarBackground(mTopDockedOpaqueWindowState);
                drawsBarBackground(mTopDockedOpaqueWindowState);

        if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
            if (fullscreenDrawsBackground && dockedDrawsBackground) {
@@ -2818,9 +2825,8 @@ public class DisplayPolicy {
            }
        }

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

+6 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -645,12 +646,11 @@ public class SizeCompatTests extends WindowTestsBase {
        assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0),
                mActivity.getLetterboxInsets());

        final BarController statusBarController =
                mActivity.mDisplayContent.getDisplayPolicy().getStatusBarController();
        final DisplayPolicy displayPolicy = mActivity.mDisplayContent.getDisplayPolicy();
        // The activity doesn't fill the display, so the letterbox of the rotated activity is
        // overlapped with the rotated content frame of status bar. Hence the status bar shouldn't
        // be transparent.
        assertFalse(statusBarController.isFullyTransparentAllowed(w));
        assertFalse(displayPolicy.isFullyTransparentAllowed(w, TYPE_STATUS_BAR));

        // Make the activity fill the display.
        prepareUnresizable(mActivity, 10 /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE);
@@ -660,7 +660,7 @@ public class SizeCompatTests extends WindowTestsBase {

        // The letterbox should only cover the notch area, so status bar can be transparent.
        assertEquals(new Rect(notchHeight, 0, 0, 0), mActivity.getLetterboxInsets());
        assertTrue(statusBarController.isFullyTransparentAllowed(w));
        assertTrue(displayPolicy.isFullyTransparentAllowed(w, TYPE_STATUS_BAR));
    }

    @Test
@@ -1020,9 +1020,9 @@ public class SizeCompatTests extends WindowTestsBase {
        displayPolicy.onConfigurationChanged();

        final TestWindowToken token = createTestWindowToken(
                WindowManager.LayoutParams.TYPE_STATUS_BAR, displayContent);
                TYPE_STATUS_BAR, displayContent);
        final WindowManager.LayoutParams attrs =
                new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_STATUS_BAR);
                new WindowManager.LayoutParams(TYPE_STATUS_BAR);
        attrs.gravity = android.view.Gravity.TOP;
        attrs.layoutInDisplayCutoutMode =
                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;