Merge "Compare letterbox and bar content frame with the same rotation" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-06-15 10:59:15 +00:00
committed by Android (Google) Code Review
6 changed files with 129 additions and 45 deletions

View File

@@ -59,6 +59,7 @@ public class BarController {
private final int mTransparentFlag;
private final int mStatusBarManagerId;
private final int mTranslucentWmFlag;
private final int mWindowType;
protected final Handler mHandler;
private final Object mServiceAquireLock = new Object();
private StatusBarManagerInternal mStatusBarInternal;
@@ -77,13 +78,14 @@ public class BarController {
private OnBarVisibilityChangedListener mVisibilityChangeListener;
BarController(String tag, int displayId, int transientFlag, int unhideFlag, int translucentFlag,
int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
int statusBarManagerId, int windowType, int translucentWmFlag, int transparentFlag) {
mTag = "BarController." + tag;
mDisplayId = displayId;
mTransientFlag = transientFlag;
mUnhideFlag = unhideFlag;
mTranslucentFlag = translucentFlag;
mStatusBarManagerId = statusBarManagerId;
mWindowType = windowType;
mTranslucentWmFlag = translucentWmFlag;
mTransparentFlag = transparentFlag;
mHandler = new BarHandler();
@@ -168,7 +170,12 @@ public class BarController {
}
boolean isTransparentAllowed(WindowState win) {
return win == null || win.letterboxNotIntersectsOrFullyContains(mContentFrame);
if (win == null) {
return true;
}
final Rect rotatedContentFrame = win.mToken.getFixedRotationBarContentFrame(mWindowType);
final Rect contentFrame = rotatedContentFrame != null ? rotatedContentFrame : mContentFrame;
return win.letterboxNotIntersectsOrFullyContains(contentFrame);
}
boolean setBarShowingLw(final boolean show) {

View File

@@ -151,6 +151,7 @@ import android.util.IntArray;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.InputChannel;
@@ -199,6 +200,7 @@ import com.android.server.wallpaper.WallpaperManagerInternal;
import com.android.server.wm.utils.InsetUtils;
import java.io.PrintWriter;
import java.util.function.Consumer;
/**
* The policy that provides the basic behaviors and states of a display to show UI.
@@ -471,6 +473,7 @@ public class DisplayPolicy {
View.NAVIGATION_BAR_UNHIDE,
View.NAVIGATION_BAR_TRANSLUCENT,
StatusBarManager.WINDOW_NAVIGATION_BAR,
TYPE_NAVIGATION_BAR,
FLAG_TRANSLUCENT_NAVIGATION,
View.NAVIGATION_BAR_TRANSPARENT);
@@ -1171,6 +1174,11 @@ public class DisplayPolicy {
displayFrames.mDisplayCutoutSafe.top);
}
@VisibleForTesting
StatusBarController getStatusBarController() {
return mStatusBarController;
}
WindowState getStatusBar() {
return mStatusBar;
}
@@ -1469,13 +1477,16 @@ public class DisplayPolicy {
}
private void simulateLayoutDecorWindow(WindowState win, DisplayFrames displayFrames,
InsetsState insetsState, WindowFrames simulatedWindowFrames, Runnable layout) {
InsetsState insetsState, WindowFrames simulatedWindowFrames,
SparseArray<Rect> contentFrames, Consumer<Rect> layout) {
win.setSimulatedWindowFrames(simulatedWindowFrames);
final Rect contentFrame = new Rect();
try {
layout.run();
layout.accept(contentFrame);
} finally {
win.setSimulatedWindowFrames(null);
}
contentFrames.put(win.mAttrs.type, contentFrame);
mDisplayContent.getInsetsStateController().computeSimulatedState(insetsState, win,
displayFrames, simulatedWindowFrames);
}
@@ -1487,24 +1498,25 @@ public class DisplayPolicy {
* state and some temporal states. In other words, it doesn't change the window frames used to
* show on screen.
*/
void simulateLayoutDisplay(DisplayFrames displayFrames, InsetsState insetsState, int uiMode) {
void simulateLayoutDisplay(DisplayFrames displayFrames, InsetsState insetsState,
SparseArray<Rect> barContentFrames) {
displayFrames.onBeginLayout();
updateInsetsStateForDisplayCutout(displayFrames, insetsState);
insetsState.setDisplayFrame(displayFrames.mUnrestricted);
final WindowFrames simulatedWindowFrames = new WindowFrames();
if (mNavigationBar != null) {
simulateLayoutDecorWindow(
mNavigationBar, displayFrames, insetsState, simulatedWindowFrames,
() -> layoutNavigationBar(displayFrames, uiMode, mLastNavVisible,
simulateLayoutDecorWindow(mNavigationBar, displayFrames, insetsState,
simulatedWindowFrames, barContentFrames,
contentFrame -> layoutNavigationBar(displayFrames,
mDisplayContent.getConfiguration().uiMode, mLastNavVisible,
mLastNavTranslucent, mLastNavAllowedHidden,
mLastNotificationShadeForcesShowingNavigation,
false /* isRealLayout */));
mLastNotificationShadeForcesShowingNavigation, contentFrame));
}
if (mStatusBar != null) {
simulateLayoutDecorWindow(
mStatusBar, displayFrames, insetsState, simulatedWindowFrames,
() -> layoutStatusBar(displayFrames, mLastSystemUiFlags,
false /* isRealLayout */));
simulateLayoutDecorWindow(mStatusBar, displayFrames, insetsState,
simulatedWindowFrames, barContentFrames,
contentFrame -> layoutStatusBar(displayFrames, mLastSystemUiFlags,
contentFrame));
}
layoutScreenDecorWindows(displayFrames, simulatedWindowFrames);
postAdjustDisplayFrames(displayFrames);
@@ -1556,9 +1568,10 @@ public class DisplayPolicy {
boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, navVisible,
navTranslucent, navAllowedHidden, notificationShadeForcesShowingNavigation,
true /* isRealLayout */);
null /* simulatedContentFrame */);
if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock);
updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui, true /* isRealLayout */);
updateSysUiVisibility |= layoutStatusBar(displayFrames, sysui,
null /* simulatedContentFrame */);
if (updateSysUiVisibility) {
updateSystemUiVisibilityLw();
}
@@ -1730,7 +1743,8 @@ public class DisplayPolicy {
displayFrames.mContent.set(dockFrame);
}
private boolean layoutStatusBar(DisplayFrames displayFrames, int sysui, boolean isRealLayout) {
private boolean layoutStatusBar(DisplayFrames displayFrames, int sysui,
Rect simulatedContentFrame) {
// decide where the status bar goes ahead of time
if (mStatusBar == null) {
return false;
@@ -1753,12 +1767,14 @@ public class DisplayPolicy {
displayFrames.mStable.top = Math.max(displayFrames.mStable.top,
displayFrames.mDisplayCutoutSafe.top);
if (isRealLayout) {
// Tell the bar controller where the collapsed status bar content is.
sTmpRect.set(windowFrames.mContentFrame);
sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
sTmpRect.top = windowFrames.mContentFrame.top; // Ignore top display cutout inset
sTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size
// Tell the bar controller where the collapsed status bar content is.
sTmpRect.set(windowFrames.mContentFrame);
sTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
sTmpRect.top = windowFrames.mContentFrame.top; // Ignore top display cutout inset
sTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size
if (simulatedContentFrame != null) {
simulatedContentFrame.set(sTmpRect);
} else {
mStatusBarController.setContentFrame(sTmpRect);
}
@@ -1795,7 +1811,7 @@ public class DisplayPolicy {
private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, boolean navVisible,
boolean navTranslucent, boolean navAllowedHidden,
boolean statusBarForcesShowingNavigation, boolean isRealLayout) {
boolean statusBarForcesShowingNavigation, Rect simulatedContentFrame) {
if (mNavigationBar == null) {
return false;
}
@@ -1899,7 +1915,9 @@ public class DisplayPolicy {
navigationFrame /* visibleFrame */, sTmpRect /* decorFrame */,
navigationFrame /* stableFrame */);
mNavigationBar.computeFrame(displayFrames);
if (isRealLayout) {
if (simulatedContentFrame != null) {
simulatedContentFrame.set(windowFrames.mContentFrame);
} else {
mNavigationBarPosition = navBarPosition;
mNavigationBarController.setContentFrame(windowFrames.mContentFrame);
}

View File

@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
@@ -90,6 +91,7 @@ public class StatusBarController extends BarController {
View.STATUS_BAR_UNHIDE,
View.STATUS_BAR_TRANSLUCENT,
StatusBarManager.WINDOW_STATUS_BAR,
TYPE_STATUS_BAR,
FLAG_TRANSLUCENT_STATUS,
View.STATUS_BAR_TRANSPARENT);
}

View File

@@ -48,6 +48,7 @@ import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayAdjustments.FixedRotationAdjustments;
import android.view.DisplayInfo;
@@ -124,7 +125,7 @@ class WindowToken extends WindowContainer<WindowState> {
private static class FixedRotationTransformState {
final DisplayInfo mDisplayInfo;
final DisplayFrames mDisplayFrames;
final InsetsState mInsetsState;
final InsetsState mInsetsState = new InsetsState();
final Configuration mRotatedOverrideConfiguration;
final SeamlessRotator mRotator;
/**
@@ -133,14 +134,14 @@ class WindowToken extends WindowContainer<WindowState> {
*/
final ArrayList<WindowToken> mAssociatedTokens = new ArrayList<>(3);
final ArrayList<WindowContainer<?>> mRotatedContainers = new ArrayList<>(3);
final SparseArray<Rect> mBarContentFrames = new SparseArray<>();
boolean mIsTransforming = true;
FixedRotationTransformState(DisplayInfo rotatedDisplayInfo,
DisplayFrames rotatedDisplayFrames, InsetsState rotatedInsetsState,
Configuration rotatedConfig, int currentRotation) {
DisplayFrames rotatedDisplayFrames, Configuration rotatedConfig,
int currentRotation) {
mDisplayInfo = rotatedDisplayInfo;
mDisplayFrames = rotatedDisplayFrames;
mInsetsState = rotatedInsetsState;
mRotatedOverrideConfiguration = rotatedConfig;
// This will use unrotate as rotate, so the new and old rotation are inverted.
mRotator = new SeamlessRotator(rotatedDisplayInfo.rotation, currentRotation,
@@ -516,6 +517,12 @@ class WindowToken extends WindowContainer<WindowState> {
: null;
}
Rect getFixedRotationBarContentFrame(int windowType) {
return isFixedRotationTransforming()
? mFixedRotationTransformState.mBarContentFrames.get(windowType)
: null;
}
InsetsState getFixedRotationTransformInsetsState() {
return isFixedRotationTransforming() ? mFixedRotationTransformState.mInsetsState : null;
}
@@ -526,12 +533,12 @@ class WindowToken extends WindowContainer<WindowState> {
if (mFixedRotationTransformState != null) {
return;
}
final InsetsState insetsState = new InsetsState();
mDisplayContent.getDisplayPolicy().simulateLayoutDisplay(displayFrames, insetsState,
mDisplayContent.getConfiguration().uiMode);
mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
insetsState, new Configuration(config), mDisplayContent.getRotation());
new Configuration(config), mDisplayContent.getRotation());
mFixedRotationTransformState.mAssociatedTokens.add(this);
mDisplayContent.getDisplayPolicy().simulateLayoutDisplay(displayFrames,
mFixedRotationTransformState.mInsetsState,
mFixedRotationTransformState.mBarContentFrames);
onConfigurationChanged(getParent().getConfiguration());
notifyFixedRotationTransform(true /* enabled */);
}

View File

@@ -57,6 +57,7 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;
import android.util.SparseArray;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.InsetsState;
@@ -776,15 +777,15 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
}
private void assertSimulateLayoutSameDisplayFrames() {
final int uiMode = 0;
final String prefix = "";
final InsetsState simulatedInsetsState = new InsetsState();
final DisplayFrames simulatedDisplayFrames = createDisplayFrames();
mDisplayPolicy.beginLayoutLw(mFrames, uiMode);
mDisplayPolicy.beginLayoutLw(mFrames, mDisplayContent.getConfiguration().uiMode);
// Force the display bounds because it is not synced with display frames in policy test.
mDisplayContent.getWindowConfiguration().setBounds(mFrames.mUnrestricted);
mDisplayContent.getInsetsStateController().onPostLayout();
mDisplayPolicy.simulateLayoutDisplay(simulatedDisplayFrames, simulatedInsetsState, uiMode);
mDisplayPolicy.simulateLayoutDisplay(simulatedDisplayFrames, simulatedInsetsState,
new SparseArray<>() /* barContentFrames */);
final StringWriter realFramesDump = new StringWriter();
mFrames.dump(prefix, new PrintWriter(realFramesDump));

View File

@@ -24,6 +24,7 @@ import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
@@ -491,7 +492,10 @@ public class SizeCompatTests extends ActivityTestsBase {
mService.mWindowManager.mIsFixedRotationTransformEnabled = true;
final int dw = 1000;
final int dh = 2500;
setUpDisplaySizeWithApp(dw, dh);
final int notchHeight = 200;
setUpApp(new TestDisplayContent.Builder(mService, dw, dh).setNotch(notchHeight).build());
addStatusBar(mActivity.mDisplayContent);
mActivity.mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
false /* alwaysKeepCurrent */);
mActivity.mDisplayContent.mOpeningApps.add(mActivity);
@@ -503,31 +507,76 @@ public class SizeCompatTests extends ActivityTestsBase {
// Display keeps in original orientation.
assertEquals(Configuration.ORIENTATION_PORTRAIT,
mActivity.mDisplayContent.getConfiguration().orientation);
// Activity bounds should be [350, 0 - 2150, 1000] in landscape. Its width=1000*1.8=1800.
// The width should be restricted by the max aspect ratio = 1000 * 1.8 = 1800.
assertEquals((int) (dw * maxAspect), mActivity.getBounds().width());
// The bounds should be horizontal centered: (2500-1900)/2=350.
assertEquals((dh - mActivity.getBounds().width()) / 2, mActivity.getBounds().left);
// The notch is at the left side of the landscape activity. The bounds should be horizontal
// centered in the remaining area [200, 0 - 2500, 1000], so its left should be
// 200 + (2300 - 1800) / 2 = 450. The bounds should be [450, 0 - 2250, 1000].
assertEquals(notchHeight + (dh - notchHeight - mActivity.getBounds().width()) / 2,
mActivity.getBounds().left);
// The letterbox needs a main window to layout.
addWindowToActivity(mActivity);
final WindowState w = addWindowToActivity(mActivity);
// Compute the frames of the window and invoke {@link ActivityRecord#layoutLetterbox}.
mActivity.mRootWindowContainer.performSurfacePlacement();
// The letterbox insets should be [350, 0 - 350, 0].
// The letterbox insets should be [450, 0 - 250, 0].
assertEquals(new Rect(mActivity.getBounds().left, 0, dh - mActivity.getBounds().right, 0),
mActivity.getLetterboxInsets());
final StatusBarController statusBarController =
mActivity.mDisplayContent.getDisplayPolicy().getStatusBarController();
// 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.isTransparentAllowed(w));
// Make the activity fill the display.
prepareUnresizable(10 /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE);
w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
// Refresh the letterbox.
mActivity.mRootWindowContainer.performSurfacePlacement();
// 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.isTransparentAllowed(w));
}
private WindowState addWindowToActivity(ActivityRecord activity) {
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
mService.mWindowManager, mock(Session.class), new TestIWindow(), params, mActivity);
activity.mWmService, mock(Session.class), new TestIWindow(), params, activity);
WindowTestsBase.makeWindowVisible(w);
w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
mActivity.addWindow(w);
activity.addWindow(w);
return w;
}
private static void addStatusBar(DisplayContent displayContent) {
final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
doReturn(true).when(displayPolicy).hasStatusBar();
displayPolicy.onConfigurationChanged();
final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(
WindowManager.LayoutParams.TYPE_STATUS_BAR, displayContent);
final WindowManager.LayoutParams attrs =
new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_STATUS_BAR);
attrs.gravity = android.view.Gravity.TOP;
attrs.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
attrs.setFitInsetsTypes(0 /* types */);
final WindowTestUtils.TestWindowState statusBar = new WindowTestUtils.TestWindowState(
displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
token.addWindow(statusBar);
statusBar.setRequestedSize(displayContent.mBaseDisplayWidth,
displayContent.getDisplayUiContext().getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height));
displayPolicy.addWindowLw(statusBar, attrs);
displayPolicy.beginLayoutLw(displayContent.mDisplayFrames,
displayContent.getConfiguration().uiMode);
}
/**
* Setup {@link #mActivity} as a size-compat-mode-able activity with fixed aspect and/or
* orientation.