diff options
| author | 2020-06-15 10:59:15 +0000 | |
|---|---|---|
| committer | 2020-06-15 10:59:15 +0000 | |
| commit | 65ddf5fa179a7fe8cd9f751d9186858be4af52cd (patch) | |
| tree | c1acd1d25ab3d81fbd86330ded93b4de7032191d | |
| parent | 40bdc176e1b5251c718dc3932c166334dd91b545 (diff) | |
| parent | 80f4f7c8fd71f508aaea83bd5a02ac1c5505f952 (diff) | |
Merge "Compare letterbox and bar content frame with the same rotation" into rvc-dev
6 files changed, 129 insertions, 45 deletions
diff --git a/services/core/java/com/android/server/wm/BarController.java b/services/core/java/com/android/server/wm/BarController.java index 8b14095874e3..26e0790a7604 100644 --- a/services/core/java/com/android/server/wm/BarController.java +++ b/services/core/java/com/android/server/wm/BarController.java @@ -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) { diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index cc4a0a255913..3c4a9ad08199 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -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); } diff --git a/services/core/java/com/android/server/wm/StatusBarController.java b/services/core/java/com/android/server/wm/StatusBarController.java index cac992a67541..3564e0bce5f5 100644 --- a/services/core/java/com/android/server/wm/StatusBarController.java +++ b/services/core/java/com/android/server/wm/StatusBarController.java @@ -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); } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 0d4cea8bc352..86aacf308068 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -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 */); } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 27c4e9ba8641..1922351ac1eb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -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)); diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 665cf83cd33c..d584d1533807 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -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. |