Merge "Remove BarController" into sc-dev

This commit is contained in:
Tiger Huang
2021-02-02 11:20:19 +00:00
committed by Android (Google) Code Review
3 changed files with 61 additions and 125 deletions

View File

@@ -1,70 +0,0 @@
/*
* 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));
}
}

View File

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

View File

@@ -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;