diff options
| author | 2022-09-02 23:29:29 -0600 | |
|---|---|---|
| committer | 2022-09-02 23:29:29 +0800 | |
| commit | 3ef46b57b93a2b3c51a6c4894b340905513ec482 (patch) | |
| tree | 30e6f59cb612c0909ae8c05eaf9bae1b47a98a3c | |
| parent | bde7caf85ea99672e31317746ae0a4125fdd77a3 (diff) | |
Optimize screen decor insets calculation
This stores the computed decor insets and frame excluding insets.
So it can save 99% time of recomputing the insets every time during
starting an activity. E.g. dozen times of "prepare display info/frame,
compute window layout of insets source windows, calculate insets"
becomes "get result from array".
The saved decor insets will be updated when:
- Display metrics is changed (DC#updateBaseDisplayMetrics).
- Insets provider is added/removed/changed.
Also
- Use DisplayCutout rather than WmDisplayCutout to simplify
passing the cutout between methods.
- Optimize getSourceProvider to avoid unnecessary object allocation.
This also fixes an issue that the display doesn't compute the latest
configuration when navigation mode is changed. Now it is fixed by
checking if the insets provider has layout changes and then recompute
screen configuration.
Bug: 238399969
Bug: 159103089
Test: atest DisplayPolicyInsetsTests DisplayPolicyLayoutTests
DisplayPolicyTests#testUpdateDisplayConfigurationByDecor
Test: Change navigation mode or display size (density) in Settings.
And then swipe-up or press home key, there won't be a
frozen effect (display configuration change).
Change-Id: If6c28a89939372e6362b92f469ef7d793e8ec215
20 files changed, 356 insertions, 521 deletions
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index c102ad3a3ace..c198098cb6ff 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -349,20 +349,6 @@ public class InsetsState implements Parcelable { return insets; } - // TODO: Remove this once the task bar is treated as navigation bar. - public Insets calculateInsetsWithInternalTypes(Rect frame, @InternalInsetsType int[] types, - boolean ignoreVisibility) { - Insets insets = Insets.NONE; - for (int i = types.length - 1; i >= 0; i--) { - InsetsSource source = mSources[types[i]]; - if (source == null) { - continue; - } - insets = Insets.max(source.calculateInsets(frame, ignoreVisibility), insets); - } - return insets; - } - public Insets calculateInsets(Rect frame, @InsetsType int types, InsetsVisibilities overrideVisibilities) { Insets insets = Insets.NONE; diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index d572b1b4aa8c..af22f803d87d 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -357,7 +357,6 @@ import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.WindowManagerService.H; import com.android.server.wm.utils.InsetUtils; -import com.android.server.wm.utils.WmDisplayCutout; import dalvik.annotation.optimization.NeverCompile; @@ -918,7 +917,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ private final Configuration mTmpConfig = new Configuration(); private final Rect mTmpBounds = new Rect(); - private final Rect mTmpOutNonDecorBounds = new Rect(); // Token for targeting this activity for assist purposes. final Binder assistToken = new Binder(); @@ -8152,10 +8150,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final int orientation = parentBounds.height() >= parentBounds.width() ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; // Compute orientation from stable parent bounds (= parent bounds with insets applied) + final DisplayInfo di = isFixedRotationTransforming() + ? getFixedRotationTransformDisplayInfo() + : mDisplayContent.getDisplayInfo(); final Task task = getTask(); - task.calculateInsetFrames(mTmpOutNonDecorBounds /* outNonDecorBounds */, - outStableBounds /* outStableBounds */, parentBounds /* bounds */, - mDisplayContent.getDisplayInfo()); + task.calculateInsetFrames(mTmpBounds /* outNonDecorBounds */, + outStableBounds /* outStableBounds */, parentBounds /* bounds */, di); final int orientationWithInsets = outStableBounds.height() >= outStableBounds.width() ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; // If orientation does not match the orientation with insets applied, then a @@ -9718,10 +9718,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); final int dw = rotated ? display.mBaseDisplayHeight : display.mBaseDisplayWidth; final int dh = rotated ? display.mBaseDisplayWidth : display.mBaseDisplayHeight; - final WmDisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation); - policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]); - mStableInsets[rotation].set(mNonDecorInsets[rotation]); - policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation); + final DisplayPolicy.DecorInsets.Info decorInfo = + policy.getDecorInsetsInfo(rotation, dw, dh); + mNonDecorInsets[rotation].set(decorInfo.mNonDecorInsets); + mStableInsets[rotation].set(decorInfo.mConfigInsets); if (unfilledContainerBounds == null) { continue; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 603a7929879b..720b08285f17 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1080,7 +1080,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * mDisplayMetrics.densityDpi / DENSITY_DEFAULT; isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; mInsetsStateController = new InsetsStateController(this); - mDisplayFrames = new DisplayFrames(mDisplayId, mInsetsStateController.getRawInsetsState(), + mDisplayFrames = new DisplayFrames(mInsetsStateController.getRawInsetsState(), mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation), calculateRoundedCornersForRotation(mDisplayInfo.rotation), calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation)); @@ -1936,11 +1936,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private void startFixedRotationTransform(WindowToken token, int rotation) { mTmpConfiguration.unset(); final DisplayInfo info = computeScreenConfiguration(mTmpConfiguration, rotation); - final WmDisplayCutout cutout = calculateDisplayCutoutForRotation(rotation); + final DisplayCutout cutout = calculateDisplayCutoutForRotation(rotation); final RoundedCorners roundedCorners = calculateRoundedCornersForRotation(rotation); final PrivacyIndicatorBounds indicatorBounds = calculatePrivacyIndicatorBoundsForRotation(rotation); - final DisplayFrames displayFrames = new DisplayFrames(mDisplayId, new InsetsState(), info, + final DisplayFrames displayFrames = new DisplayFrames(new InsetsState(), info, cutout, roundedCorners, indicatorBounds); token.applyFixedRotationTransform(info, displayFrames, mTmpConfiguration); } @@ -2147,12 +2147,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; // Update application display metrics. - final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation); - final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout(); + final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation); final RoundedCorners roundedCorners = calculateRoundedCornersForRotation(rotation); - final Rect appFrame = mDisplayPolicy.getNonDecorDisplayFrame(dw, dh, rotation, - wmDisplayCutout); + final Rect appFrame = mDisplayPolicy.getDecorInsetsInfo(rotation, dw, dh).mNonDecorFrame; mDisplayInfo.rotation = rotation; mDisplayInfo.logicalWidth = dw; mDisplayInfo.logicalHeight = dh; @@ -2190,9 +2188,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mDisplayInfo; } - WmDisplayCutout calculateDisplayCutoutForRotation(int rotation) { + DisplayCutout calculateDisplayCutoutForRotation(int rotation) { return mDisplayCutoutCache.getOrCompute( - mIsSizeForced ? mBaseDisplayCutout : mInitialDisplayCutout, rotation); + mIsSizeForced ? mBaseDisplayCutout : mInitialDisplayCutout, rotation) + .getDisplayCutout(); } static WmDisplayCutout calculateDisplayCutoutForRotationAndDisplaySizeUncached( @@ -2263,9 +2262,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; outConfig.windowConfiguration.setMaxBounds(0, 0, dw, dh); outConfig.windowConfiguration.setBounds(outConfig.windowConfiguration.getMaxBounds()); - - final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation); - computeScreenAppConfiguration(outConfig, dw, dh, rotation, wmDisplayCutout); + computeScreenAppConfiguration(outConfig, dw, dh, rotation); final DisplayInfo displayInfo = new DisplayInfo(mDisplayInfo); displayInfo.rotation = rotation; @@ -2274,7 +2271,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp final Rect appBounds = outConfig.windowConfiguration.getAppBounds(); displayInfo.appWidth = appBounds.width(); displayInfo.appHeight = appBounds.height(); - final DisplayCutout displayCutout = wmDisplayCutout.getDisplayCutout(); + final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation); displayInfo.displayCutout = displayCutout.isEmpty() ? null : displayCutout; computeSizeRangesAndScreenLayout(displayInfo, rotated, dw, dh, mDisplayMetrics.density, outConfig); @@ -2283,21 +2280,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** Compute configuration related to application without changing current display. */ private void computeScreenAppConfiguration(Configuration outConfig, int dw, int dh, - int rotation, WmDisplayCutout wmDisplayCutout) { - final DisplayFrames displayFrames = - mDisplayPolicy.getSimulatedDisplayFrames(rotation, dw, dh, wmDisplayCutout); - final Rect appFrame = - mDisplayPolicy.getNonDecorDisplayFrameWithSimulatedFrame(displayFrames); + int rotation) { + final DisplayPolicy.DecorInsets.Info info = + mDisplayPolicy.getDecorInsetsInfo(rotation, dw, dh); // AppBounds at the root level should mirror the app screen size. - outConfig.windowConfiguration.setAppBounds(appFrame); + outConfig.windowConfiguration.setAppBounds(info.mNonDecorFrame); outConfig.windowConfiguration.setRotation(rotation); outConfig.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; final float density = mDisplayMetrics.density; - final Point configSize = - mDisplayPolicy.getConfigDisplaySizeWithSimulatedFrame(displayFrames); - outConfig.screenWidthDp = (int) (configSize.x / density + 0.5f); - outConfig.screenHeightDp = (int) (configSize.y / density + 0.5f); + outConfig.screenWidthDp = (int) (info.mConfigFrame.width() / density + 0.5f); + outConfig.screenHeightDp = (int) (info.mConfigFrame.height() / density + 0.5f); outConfig.compatScreenWidthDp = (int) (outConfig.screenWidthDp / mCompatibleScreenScale); outConfig.compatScreenHeightDp = (int) (outConfig.screenHeightDp / mCompatibleScreenScale); @@ -2320,8 +2313,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp config.windowConfiguration.setWindowingMode(getWindowingMode()); config.windowConfiguration.setDisplayWindowingMode(getWindowingMode()); - computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation, - calculateDisplayCutoutForRotation(getRotation())); + computeScreenAppConfiguration(config, dw, dh, displayInfo.rotation); config.screenLayout = (config.screenLayout & ~Configuration.SCREENLAYOUT_ROUND_MASK) | ((displayInfo.flags & Display.FLAG_ROUND) != 0 @@ -2430,9 +2422,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm, int dw, int dh) { - final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation); - final Rect nonDecorSize = mDisplayPolicy.getNonDecorDisplayFrame(dw, dh, rotation, - wmDisplayCutout); + final Rect nonDecorSize = + mDisplayPolicy.getDecorInsetsInfo(rotation, dw, dh).mNonDecorFrame; dm.noncompatWidthPixels = nonDecorSize.width(); dm.noncompatHeightPixels = nonDecorSize.height(); float scale = CompatibilityInfo.computeCompatibleScaling(dm, null); @@ -2481,11 +2472,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh) { - // Get the display cutout at this rotation. - final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation); - // Get the app screen size at this rotation. - final Rect size = mDisplayPolicy.getNonDecorDisplayFrame(dw, dh, rotation, wmDisplayCutout); + final Rect size = mDisplayPolicy.getDecorInsetsInfo(rotation, dw, dh).mNonDecorFrame; // Compute the screen layout size class for this rotation. int longSize = size.width(); @@ -2501,19 +2489,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } private void adjustDisplaySizeRanges(DisplayInfo displayInfo, int rotation, int dw, int dh) { - final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(rotation); - final Point size = mDisplayPolicy.getConfigDisplaySize(dw, dh, rotation, wmDisplayCutout); - if (size.x < displayInfo.smallestNominalAppWidth) { - displayInfo.smallestNominalAppWidth = size.x; + final DisplayPolicy.DecorInsets.Info info = mDisplayPolicy.getDecorInsetsInfo( + rotation, dw, dh); + final int w = info.mConfigFrame.width(); + final int h = info.mConfigFrame.height(); + if (w < displayInfo.smallestNominalAppWidth) { + displayInfo.smallestNominalAppWidth = w; } - if (size.x > displayInfo.largestNominalAppWidth) { - displayInfo.largestNominalAppWidth = size.x; + if (w > displayInfo.largestNominalAppWidth) { + displayInfo.largestNominalAppWidth = w; } - if (size.y < displayInfo.smallestNominalAppHeight) { - displayInfo.smallestNominalAppHeight = size.y; + if (h < displayInfo.smallestNominalAppHeight) { + displayInfo.smallestNominalAppHeight = h; } - if (size.y > displayInfo.largestNominalAppHeight) { - displayInfo.largestNominalAppHeight = size.y; + if (h > displayInfo.largestNominalAppHeight) { + displayInfo.largestNominalAppHeight = h; } } @@ -2773,14 +2763,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } private void updateDisplayFrames(boolean notifyInsetsChange) { - if (mDisplayFrames.update(mDisplayInfo, - calculateDisplayCutoutForRotation(mDisplayInfo.rotation), - calculateRoundedCornersForRotation(mDisplayInfo.rotation), - calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation))) { + if (updateDisplayFrames(mDisplayFrames, mDisplayInfo.rotation, + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) { mInsetsStateController.onDisplayFramesUpdated(notifyInsetsChange); } } + boolean updateDisplayFrames(DisplayFrames displayFrames, int rotation, int w, int h) { + return displayFrames.update(rotation, w, h, + calculateDisplayCutoutForRotation(rotation), + calculateRoundedCornersForRotation(rotation), + calculatePrivacyIndicatorBoundsForRotation(rotation)); + } + @Override void onDisplayChanged(DisplayContent dc) { super.onDisplayChanged(dc); @@ -2943,6 +2938,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp + mBaseDisplayHeight + " on display:" + getDisplayId()); } } + if (mDisplayReady) { + mDisplayPolicy.mDecorInsets.invalidate(); + } } /** @@ -5584,7 +5582,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp outExclusionUnrestricted.setEmpty(); } final Region unhandled = Region.obtain(); - unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight); + unhandled.set(0, 0, mDisplayFrames.mWidth, mDisplayFrames.mHeight); final Rect leftEdge = mInsetsStateController.getSourceProvider(ITYPE_LEFT_GESTURES) .getSource().getFrame(); diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java index 7ca38b8fcc00..33641f72b2ff 100644 --- a/services/core/java/com/android/server/wm/DisplayFrames.java +++ b/services/core/java/com/android/server/wm/DisplayFrames.java @@ -30,8 +30,6 @@ import android.view.InsetsState; import android.view.PrivacyIndicatorBounds; import android.view.RoundedCorners; -import com.android.server.wm.utils.WmDisplayCutout; - import java.io.PrintWriter; /** @@ -39,8 +37,6 @@ import java.io.PrintWriter; * @hide */ public class DisplayFrames { - public final int mDisplayId; - public final InsetsState mInsetsState; /** @@ -54,48 +50,45 @@ public class DisplayFrames { */ public final Rect mDisplayCutoutSafe = new Rect(); - public int mDisplayWidth; - public int mDisplayHeight; + public int mWidth; + public int mHeight; public int mRotation; - public DisplayFrames(int displayId, InsetsState insetsState, DisplayInfo info, - WmDisplayCutout displayCutout, RoundedCorners roundedCorners, - PrivacyIndicatorBounds indicatorBounds) { - mDisplayId = displayId; + public DisplayFrames(InsetsState insetsState, DisplayInfo info, DisplayCutout cutout, + RoundedCorners roundedCorners, PrivacyIndicatorBounds indicatorBounds) { mInsetsState = insetsState; - update(info, displayCutout, roundedCorners, indicatorBounds); + update(info.rotation, info.logicalWidth, info.logicalHeight, cutout, roundedCorners, + indicatorBounds); + } + + DisplayFrames() { + mInsetsState = new InsetsState(); } /** - * This is called when {@link DisplayInfo} or {@link PrivacyIndicatorBounds} is updated. + * This is called if the display info may be changed, e.g. rotation, size, insets. * - * @param info the updated {@link DisplayInfo}. - * @param displayCutout the updated {@link DisplayCutout}. - * @param roundedCorners the updated {@link RoundedCorners}. - * @param indicatorBounds the updated {@link PrivacyIndicatorBounds}. * @return {@code true} if anything has been changed; {@code false} otherwise. */ - public boolean update(DisplayInfo info, @NonNull WmDisplayCutout displayCutout, + public boolean update(int rotation, int w, int h, @NonNull DisplayCutout displayCutout, @NonNull RoundedCorners roundedCorners, @NonNull PrivacyIndicatorBounds indicatorBounds) { final InsetsState state = mInsetsState; final Rect safe = mDisplayCutoutSafe; - final DisplayCutout cutout = displayCutout.getDisplayCutout(); - if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight - && mRotation == info.rotation - && state.getDisplayCutout().equals(cutout) + if (mRotation == rotation && mWidth == w && mHeight == h + && mInsetsState.getDisplayCutout().equals(displayCutout) && state.getRoundedCorners().equals(roundedCorners) && state.getPrivacyIndicatorBounds().equals(indicatorBounds)) { return false; } - mDisplayWidth = info.logicalWidth; - mDisplayHeight = info.logicalHeight; - mRotation = info.rotation; + mRotation = rotation; + mWidth = w; + mHeight = h; final Rect unrestricted = mUnrestricted; - unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight); + unrestricted.set(0, 0, w, h); state.setDisplayFrame(unrestricted); - state.setDisplayCutout(cutout); + state.setDisplayCutout(displayCutout); state.setRoundedCorners(roundedCorners); state.setPrivacyIndicatorBounds(indicatorBounds); state.getDisplayCutoutSafe(safe); @@ -132,7 +125,6 @@ public class DisplayFrames { } public void dump(String prefix, PrintWriter pw) { - pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight - + " r=" + mRotation); + pw.println(prefix + "DisplayFrames w=" + mWidth + " h=" + mHeight + " r=" + mRotation); } } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 713c13e7fa10..fe7cb1935f7a 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -19,19 +19,15 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.view.Display.TYPE_INTERNAL; -import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES; import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_CLIMATE_BAR; import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_LEFT_GESTURES; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_RIGHT_GESTURES; import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT; import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES; import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; @@ -107,7 +103,6 @@ import android.content.Intent; import android.content.res.Resources; import android.graphics.Insets; import android.graphics.PixelFormat; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.gui.DropInputMode; @@ -132,8 +127,6 @@ import android.view.InsetsSource; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; import android.view.InsetsVisibilities; -import android.view.PrivacyIndicatorBounds; -import android.view.RoundedCorners; import android.view.Surface; import android.view.View; import android.view.ViewDebug; @@ -151,7 +144,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.ForceShowNavBarSettingsObserver; import com.android.internal.policy.GestureNavigationSettingsObserver; import com.android.internal.policy.ScreenDecorationsUtils; -import com.android.internal.policy.SystemBarUtils; import com.android.internal.protolog.common.ProtoLog; import com.android.internal.statusbar.LetterboxDetails; import com.android.internal.util.ScreenshotHelper; @@ -166,7 +158,6 @@ import com.android.server.policy.WindowManagerPolicy.ScreenOnListener; import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.wallpaper.WallpaperManagerInternal; -import com.android.server.wm.utils.WmDisplayCutout; import java.io.PrintWriter; import java.util.ArrayList; @@ -242,6 +233,8 @@ public class DisplayPolicy { private final SystemGesturesPointerEventListener mSystemGestures; + final DecorInsets mDecorInsets; + private volatile int mLidState = LID_ABSENT; private volatile int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; private volatile boolean mHdmiPlugged; @@ -266,7 +259,6 @@ public class DisplayPolicy { private WindowState mStatusBar = null; private volatile WindowState mNotificationShade; - private final int[] mStatusBarHeightForRotation = new int[4]; private WindowState mNavigationBar = null; @NavigationBarPosition private int mNavigationBarPosition = NAV_BAR_BOTTOM; @@ -353,7 +345,6 @@ public class DisplayPolicy { private static final Rect sTmpRect = new Rect(); private static final Rect sTmpRect2 = new Rect(); - private static final Rect sTmpLastParentFrame = new Rect(); private static final Rect sTmpDisplayCutoutSafe = new Rect(); private static final ClientWindowFrames sTmpClientFrames = new ClientWindowFrames(); @@ -391,16 +382,6 @@ public class DisplayPolicy { private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0; private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1; - // TODO (b/235842600): Use public type once we can treat task bar as navigation bar. - private static final int[] STABLE_TYPES = new int[]{ - ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT, ITYPE_BOTTOM_DISPLAY_CUTOUT, - ITYPE_LEFT_DISPLAY_CUTOUT, ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR, ITYPE_CLIMATE_BAR - }; - private static final int[] NON_DECOR_TYPES = new int[]{ - ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT, ITYPE_BOTTOM_DISPLAY_CUTOUT, - ITYPE_LEFT_DISPLAY_CUTOUT, ITYPE_NAVIGATION_BAR - }; - private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver; private final WindowManagerInternal.AppTransitionListener mAppTransitionListener; @@ -444,6 +425,7 @@ public class DisplayPolicy { : service.mAtmService.mSystemThread .getSystemUiContext(displayContent.getDisplayId()); mDisplayContent = displayContent; + mDecorInsets = new DecorInsets(displayContent); mLock = service.getWindowManagerLock(); final int displayId = displayContent.getDisplayId(); @@ -1227,7 +1209,7 @@ public class DisplayPolicy { Math.max(displayFrames.mDisplayCutoutSafe.left, 0); inOutFrame.left = 0; inOutFrame.top = 0; - inOutFrame.bottom = displayFrames.mDisplayHeight; + inOutFrame.bottom = displayFrames.mHeight; inOutFrame.right = leftSafeInset + mLeftGestureInset; }); mDisplayContent.setInsetProvider(ITYPE_RIGHT_GESTURES, win, @@ -1237,8 +1219,8 @@ public class DisplayPolicy { displayFrames.mUnrestricted.right); inOutFrame.left = rightSafeInset - mRightGestureInset; inOutFrame.top = 0; - inOutFrame.bottom = displayFrames.mDisplayHeight; - inOutFrame.right = displayFrames.mDisplayWidth; + inOutFrame.bottom = displayFrames.mHeight; + inOutFrame.right = displayFrames.mWidth; }); mDisplayContent.setInsetProvider(ITYPE_BOTTOM_TAPPABLE_ELEMENT, win, (displayFrames, windowContainer, inOutFrame) -> { @@ -1429,11 +1411,6 @@ public class DisplayPolicy { return Math.max(statusBarHeight, displayFrames.mDisplayCutoutSafe.top); } - @VisibleForTesting - int getStatusBarHeightForRotation(@Surface.Rotation int rotation) { - return SystemBarUtils.getStatusBarHeightForRotation(mUiContext, rotation); - } - WindowState getStatusBar() { return mStatusBar != null ? mStatusBar : mStatusBarAlt; } @@ -1929,25 +1906,11 @@ public class DisplayPolicy { final Resources res = getCurrentUserResources(); final int portraitRotation = displayRotation.getPortraitRotation(); - final int upsideDownRotation = displayRotation.getUpsideDownRotation(); - final int landscapeRotation = displayRotation.getLandscapeRotation(); - final int seascapeRotation = displayRotation.getSeascapeRotation(); if (hasStatusBar()) { - mStatusBarHeightForRotation[portraitRotation] = - mStatusBarHeightForRotation[upsideDownRotation] = - getStatusBarHeightForRotation(portraitRotation); - mStatusBarHeightForRotation[landscapeRotation] = - getStatusBarHeightForRotation(landscapeRotation); - mStatusBarHeightForRotation[seascapeRotation] = - getStatusBarHeightForRotation(seascapeRotation); mDisplayCutoutTouchableRegionSize = res.getDimensionPixelSize( R.dimen.display_cutout_touchable_region_size); } else { - mStatusBarHeightForRotation[portraitRotation] = - mStatusBarHeightForRotation[upsideDownRotation] = - mStatusBarHeightForRotation[landscapeRotation] = - mStatusBarHeightForRotation[seascapeRotation] = 0; mDisplayCutoutTouchableRegionSize = 0; } @@ -2053,33 +2016,9 @@ public class DisplayPolicy { } /** - * Return the display frame available after excluding any screen decorations that could never be - * removed in Honeycomb. That is, system bar or button bar. - * - * @return display frame excluding all non-decor insets. - */ - Rect getNonDecorDisplayFrame(int fullWidth, int fullHeight, int rotation, - WmDisplayCutout cutout) { - final DisplayFrames displayFrames = - getSimulatedDisplayFrames(rotation, fullWidth, fullHeight, cutout); - return getNonDecorDisplayFrameWithSimulatedFrame(displayFrames); - } - - Rect getNonDecorDisplayFrameWithSimulatedFrame(DisplayFrames displayFrames) { - final Rect nonDecorInsets = - getInsetsWithInternalTypes(displayFrames, NON_DECOR_TYPES).toRect(); - final Rect displayFrame = new Rect(displayFrames.mInsetsState.getDisplayFrame()); - displayFrame.inset(nonDecorInsets); - return displayFrame; - } - - /** * Get the Navigation Bar Frame height. This dimension is the height of the navigation bar that * is used for spacing to show additional buttons on the navigation bar (such as the ime - * switcher when ime is visible) while {@link #getNavigationBarHeight} is used for the visible - * height that we send to the app as content insets that can be smaller. - * <p> - * In car mode it will return the same height as {@link #getNavigationBarHeight} + * switcher when ime is visible). * * @param rotation specifies rotation to return dimension from * @return navigation bar frame height @@ -2092,26 +2031,6 @@ public class DisplayPolicy { } /** - * Return the available screen size that we should report for the - * configuration. This must be no larger than - * {@link #getNonDecorDisplayFrame(int, int, int, DisplayCutout)}; it may be smaller - * than that to account for more transient decoration like a status bar. - */ - public Point getConfigDisplaySize(int fullWidth, int fullHeight, int rotation, - WmDisplayCutout wmDisplayCutout) { - final DisplayFrames displayFrames = getSimulatedDisplayFrames(rotation, fullWidth, - fullHeight, wmDisplayCutout); - return getConfigDisplaySizeWithSimulatedFrame(displayFrames); - } - - Point getConfigDisplaySizeWithSimulatedFrame(DisplayFrames displayFrames) { - final Insets insets = getInsetsWithInternalTypes(displayFrames, STABLE_TYPES); - Rect configFrame = new Rect(displayFrames.mInsetsState.getDisplayFrame()); - configFrame.inset(insets); - return new Point(configFrame.width(), configFrame.height()); - } - - /** * Return corner radius in pixels that should be used on windows in order to cover the display. * * The radius is only valid for internal displays, since the corner radius of external displays @@ -2126,89 +2045,152 @@ public class DisplayPolicy { return mShowingDream; } - /** - * Calculates the stable insets if we already have the non-decor insets. - * - * @param inOutInsets The known non-decor insets. It will be modified to stable insets. - * @param rotation The current display rotation. - */ - void convertNonDecorInsetsToStableInsets(Rect inOutInsets, int rotation) { - inOutInsets.top = Math.max(inOutInsets.top, mStatusBarHeightForRotation[rotation]); - } + /** The latest insets and frames for screen configuration calculation. */ + static class DecorInsets { + static class Info { + /** + * The insets for the areas that could never be removed, i.e. display cutout and + * navigation bar. Note that its meaning is actually "decor insets". The "non" is just + * because it is used to calculate {@link #mNonDecorFrame}. + */ + final Rect mNonDecorInsets = new Rect(); + + /** + * The stable insets that can affect configuration. The sources are usually from + * display cutout, navigation bar, and status bar. + */ + final Rect mConfigInsets = new Rect(); + + /** The display frame available after excluding {@link #mNonDecorInsets}. */ + final Rect mNonDecorFrame = new Rect(); + + /** + * The available (stable) screen size that we should report for the configuration. + * This must be no larger than {@link #mNonDecorFrame}; it may be smaller than that + * to account for more transient decoration like a status bar. + */ + final Rect mConfigFrame = new Rect(); + + private boolean mNeedUpdate = true; + + void update(DisplayContent dc, int rotation, int w, int h) { + final DisplayFrames df = new DisplayFrames(); + dc.updateDisplayFrames(df, rotation, w, h); + dc.getDisplayPolicy().simulateLayoutDisplay(df); + final InsetsState insetsState = df.mInsetsState; + final Rect displayFrame = insetsState.getDisplayFrame(); + final Insets decor = calculateDecorInsetsWithInternalTypes(insetsState); + final Insets statusBar = insetsState.calculateInsets(displayFrame, + Type.statusBars(), true /* ignoreVisibility */); + mNonDecorInsets.set(decor.left, decor.top, decor.right, decor.bottom); + mConfigInsets.set(Math.max(statusBar.left, decor.left), + Math.max(statusBar.top, decor.top), + Math.max(statusBar.right, decor.right), + Math.max(statusBar.bottom, decor.bottom)); + mNonDecorFrame.set(displayFrame); + mNonDecorFrame.inset(mNonDecorInsets); + mConfigFrame.set(displayFrame); + mConfigFrame.inset(mConfigInsets); + mNeedUpdate = false; + } - /** - * Calculates the stable insets without running a layout. - * - * @param displayRotation the current display rotation - * @param displayWidth full display width - * @param displayHeight full display height - * @param displayCutout the current display cutout - * @param outInsets the insets to return - */ - public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, - WmDisplayCutout displayCutout, Rect outInsets) { - final DisplayFrames displayFrames = getSimulatedDisplayFrames(displayRotation, - displayWidth, displayHeight, displayCutout); - getStableInsetsWithSimulatedFrame(displayFrames, outInsets); - } + void set(Info other) { + mNonDecorInsets.set(other.mNonDecorInsets); + mConfigInsets.set(other.mConfigInsets); + mNonDecorFrame.set(other.mNonDecorFrame); + mConfigFrame.set(other.mConfigFrame); + mNeedUpdate = false; + } - void getStableInsetsWithSimulatedFrame(DisplayFrames displayFrames, Rect outInsets) { - // Navigation bar, status bar, and cutout. - outInsets.set(getInsetsWithInternalTypes(displayFrames, STABLE_TYPES).toRect()); + @Override + public String toString() { + return "{nonDecorInsets=" + mNonDecorInsets + + ", configInsets=" + mConfigInsets + + ", nonDecorFrame=" + mNonDecorFrame + + ", configFrame=" + mConfigFrame + '}'; + } + } + + // TODO (b/235842600): Use public type once we can treat task bar as navigation bar. + static final int[] INTERNAL_DECOR_TYPES; + static { + final ArraySet<Integer> decorTypes = InsetsState.toInternalType( + Type.displayCutout() | Type.navigationBars()); + decorTypes.remove(ITYPE_EXTRA_NAVIGATION_BAR); + INTERNAL_DECOR_TYPES = new int[decorTypes.size()]; + for (int i = 0; i < INTERNAL_DECOR_TYPES.length; i++) { + INTERNAL_DECOR_TYPES[i] = decorTypes.valueAt(i); + } + } + + private final DisplayContent mDisplayContent; + private final Info[] mInfoForRotation = new Info[4]; + final Info mTmpInfo = new Info(); + + DecorInsets(DisplayContent dc) { + mDisplayContent = dc; + for (int i = mInfoForRotation.length - 1; i >= 0; i--) { + mInfoForRotation[i] = new Info(); + } + } + + Info get(int rotation, int w, int h) { + final Info info = mInfoForRotation[rotation]; + if (info.mNeedUpdate) { + info.update(mDisplayContent, rotation, w, h); + } + return info; + } + + /** Called when the screen decor insets providers have changed. */ + void invalidate() { + for (Info info : mInfoForRotation) { + info.mNeedUpdate = true; + } + } + + // TODO (b/235842600): Remove this method once we can treat task bar as navigation bar. + private static Insets calculateDecorInsetsWithInternalTypes(InsetsState state) { + final Rect frame = state.getDisplayFrame(); + Insets insets = Insets.NONE; + for (int i = INTERNAL_DECOR_TYPES.length - 1; i >= 0; i--) { + final InsetsSource source = state.peekSource(INTERNAL_DECOR_TYPES[i]); + if (source != null) { + insets = Insets.max(source.calculateInsets(frame, true /* ignoreVisibility */), + insets); + } + } + return insets; + } } /** - * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system - * bar or button bar. See {@link #getNonDecorDisplayFrame}. - * - * @param displayRotation the current display rotation - * @param fullWidth the width of the display, including all insets - * @param fullHeight the height of the display, including all insets - * @param cutout the current display cutout - * @param outInsets the insets to return + * If the decor insets changes, the display configuration may be affected. The caller should + * call {@link DisplayContent#sendNewConfiguration()} if this method returns {@code true}. */ - public void getNonDecorInsetsLw(int displayRotation, int fullWidth, int fullHeight, - WmDisplayCutout cutout, Rect outInsets) { - final DisplayFrames displayFrames = - getSimulatedDisplayFrames(displayRotation, fullWidth, fullHeight, cutout); - getNonDecorInsetsWithSimulatedFrame(displayFrames, outInsets); - } - - void getNonDecorInsetsWithSimulatedFrame(DisplayFrames displayFrames, Rect outInsets) { - outInsets.set(getInsetsWithInternalTypes(displayFrames, NON_DECOR_TYPES).toRect()); - } - - DisplayFrames getSimulatedDisplayFrames(int displayRotation, int fullWidth, - int fullHeight, WmDisplayCutout cutout) { - final DisplayInfo info = new DisplayInfo(mDisplayContent.getDisplayInfo()); - info.rotation = displayRotation; - info.logicalWidth = fullWidth; - info.logicalHeight = fullHeight; - info.displayCutout = cutout.getDisplayCutout(); - final RoundedCorners roundedCorners = - mDisplayContent.calculateRoundedCornersForRotation(displayRotation); - final PrivacyIndicatorBounds indicatorBounds = - mDisplayContent.calculatePrivacyIndicatorBoundsForRotation(displayRotation); - final DisplayFrames displayFrames = new DisplayFrames(getDisplayId(), new InsetsState(), - info, cutout, roundedCorners, indicatorBounds); - simulateLayoutDisplay(displayFrames); - return displayFrames; - } - - @VisibleForTesting - Insets getInsets(DisplayFrames displayFrames, @InsetsType int type) { - final InsetsState state = displayFrames.mInsetsState; - final Insets insets = state.calculateInsets(state.getDisplayFrame(), type, - true /* ignoreVisibility */); - return insets; + boolean updateDecorInsetsInfoIfNeeded(WindowState win) { + if (!win.providesNonDecorInsets()) { + return false; + } + final DisplayFrames displayFrames = mDisplayContent.mDisplayFrames; + final int rotation = displayFrames.mRotation; + final int dw = displayFrames.mWidth; + final int dh = displayFrames.mHeight; + final DecorInsets.Info newInfo = mDecorInsets.mTmpInfo; + newInfo.update(mDisplayContent, rotation, dw, dh); + final DecorInsets.Info currentInfo = getDecorInsetsInfo(rotation, dw, dh); + if (newInfo.mNonDecorFrame.equals(currentInfo.mNonDecorFrame)) { + return false; + } + mDecorInsets.invalidate(); + mDecorInsets.mInfoForRotation[rotation].set(newInfo); + // If the device is booting, let the boot procedure trigger the new configuration. + // Otherwise the display configuration needs to be recomputed now. + return mService.mDisplayEnabled; } - Insets getInsetsWithInternalTypes(DisplayFrames displayFrames, - @InternalInsetsType int[] types) { - final InsetsState state = displayFrames.mInsetsState; - final Insets insets = state.calculateInsetsWithInternalTypes(state.getDisplayFrame(), types, - true /* ignoreVisibility */); - return insets; + DecorInsets.Info getDecorInsetsInfo(int rotation, int w, int h) { + return mDecorInsets.get(rotation, w, h); } @NavigationBarPosition @@ -2851,6 +2833,11 @@ public class DisplayPolicy { pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars="); pw.println(mDisplayContent.getInsetsPolicy().getRemoteInsetsControllerControlsSystemBars()); + pw.print(prefix); pw.println("mDecorInsetsInfo:"); + for (int rotation = 0; rotation < mDecorInsets.mInfoForRotation.length; rotation++) { + final DecorInsets.Info info = mDecorInsets.mInfoForRotation[rotation]; + pw.println(prefixInner + Surface.rotationToString(rotation) + "=" + info); + } mSystemGestures.dump(pw, prefix); pw.print(prefix); pw.println("Looper state:"); diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index ed771c202c04..ac1fbc35325a 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -34,6 +34,7 @@ import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; import android.util.SparseArray; +import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsState.InternalInsetsType; @@ -44,6 +45,7 @@ import com.android.server.inputmethod.InputMethodManagerInternal; import java.io.PrintWriter; import java.util.ArrayList; import java.util.function.Consumer; +import java.util.function.Function; /** * Manages global window inset state in the system represented by {@link InsetsState}. @@ -86,8 +88,17 @@ class InsetsStateController { } }; + private final Function<Integer, WindowContainerInsetsSourceProvider> mSourceProviderFunc; + InsetsStateController(DisplayContent displayContent) { mDisplayContent = displayContent; + mSourceProviderFunc = type -> { + final InsetsSource source = mState.getSource(type); + if (type == ITYPE_IME) { + return new ImeInsetsSourceProvider(source, this, mDisplayContent); + } + return new WindowContainerInsetsSourceProvider(source, this, mDisplayContent); + }; } InsetsState getRawInsetsState() { @@ -115,15 +126,7 @@ class InsetsStateController { * @return The provider of a specific type. */ WindowContainerInsetsSourceProvider getSourceProvider(@InternalInsetsType int type) { - if (type == ITYPE_IME) { - return mProviders.computeIfAbsent(type, - key -> new ImeInsetsSourceProvider( - mState.getSource(key), this, mDisplayContent)); - } else { - return mProviders.computeIfAbsent(type, - key -> new WindowContainerInsetsSourceProvider(mState.getSource(key), this, - mDisplayContent)); - } + return mProviders.computeIfAbsent(type, mSourceProviderFunc); } ImeInsetsSourceProvider getImeSourceProvider() { diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index da731e842aea..01f1a0d13af3 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -98,7 +98,6 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; import com.android.server.am.HostingRecord; import com.android.server.pm.parsing.pkg.AndroidPackage; -import com.android.server.wm.utils.WmDisplayCutout; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -298,10 +297,11 @@ class TaskFragment extends WindowContainer<WindowContainer> { final Point mLastSurfaceSize = new Point(); - private final Rect mTmpInsets = new Rect(); private final Rect mTmpBounds = new Rect(); private final Rect mTmpFullBounds = new Rect(); + /** For calculating screenWidthDp and screenWidthDp, i.e. the area without the system bars. */ private final Rect mTmpStableBounds = new Rect(); + /** For calculating app bounds, i.e. the area without the nav bar and display cutout. */ private final Rect mTmpNonDecorBounds = new Rect(); //TODO(b/207481538) Remove once the infrastructure to support per-activity screenshot is @@ -2202,21 +2202,16 @@ class TaskFragment extends WindowContainer<WindowContainer> { DisplayInfo displayInfo) { outNonDecorBounds.set(bounds); outStableBounds.set(bounds); - final Task rootTask = getRootTaskFragment().asTask(); - if (rootTask == null || rootTask.mDisplayContent == null) { + if (mDisplayContent == null) { return; } mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); - final DisplayPolicy policy = rootTask.mDisplayContent.getDisplayPolicy(); - final WmDisplayCutout cutout = - rootTask.mDisplayContent.calculateDisplayCutoutForRotation(displayInfo.rotation); - final DisplayFrames displayFrames = policy.getSimulatedDisplayFrames(displayInfo.rotation, - displayInfo.logicalWidth, displayInfo.logicalHeight, cutout); - policy.getNonDecorInsetsWithSimulatedFrame(displayFrames, mTmpInsets); - intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets); - policy.getStableInsetsWithSimulatedFrame(displayFrames, mTmpInsets); - intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets); + final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); + final DisplayPolicy.DecorInsets.Info info = policy.getDecorInsetsInfo( + displayInfo.rotation, displayInfo.logicalWidth, displayInfo.logicalHeight); + intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, info.mNonDecorInsets); + intersectWithInsetsIfFits(outStableBounds, mTmpBounds, info.mConfigInsets); } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 68198339f8b5..cc17b5b50039 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -319,7 +319,6 @@ import com.android.server.policy.WindowManagerPolicy; import com.android.server.policy.WindowManagerPolicy.ScreenOffListener; import com.android.server.power.ShutdownThread; import com.android.server.utils.PriorityDump; -import com.android.server.wm.utils.WmDisplayCutout; import dalvik.annotation.optimization.NeverCompile; @@ -1857,7 +1856,7 @@ public class WindowManagerService extends IWindowManager.Stub + ": window=%s Callers=%s", client.asBinder(), win, Debug.getCallers(5)); if ((win.isVisibleRequestedOrAdding() && displayContent.updateOrientation()) - || win.providesNonDecorInsets()) { + || displayPolicy.updateDecorInsetsInfoIfNeeded(win)) { displayContent.sendNewConfiguration(); } @@ -2254,7 +2253,7 @@ public class WindowManagerService extends IWindowManager.Stub Arrays.fill(outActiveControls, null); } int result = 0; - boolean configChanged; + boolean configChanged = false; final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); @@ -2321,10 +2320,15 @@ public class WindowManagerService extends IWindowManager.Stub flagChanges = win.mAttrs.flags ^ attrs.flags; privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags; attrChanges = win.mAttrs.copyFrom(attrs); - if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED - | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) { + final boolean layoutChanged = + (attrChanges & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0; + if (layoutChanged || (attrChanges + & WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) { win.mLayoutNeeded = true; } + if (layoutChanged) { + configChanged = displayPolicy.updateDecorInsetsInfoIfNeeded(win); + } if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0 || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) { win.mActivityRecord.checkKeyguardFlagsChanged(); @@ -2534,7 +2538,7 @@ public class WindowManagerService extends IWindowManager.Stub } Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientation"); - configChanged = displayContent.updateOrientation(); + configChanged |= displayContent.updateOrientation(); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (toBeDisplayed && win.mIsWallpaper) { @@ -7177,9 +7181,8 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayContent dc = mRoot.getDisplayContent(displayId); if (dc != null) { final DisplayInfo di = dc.getDisplayInfo(); - final WmDisplayCutout cutout = dc.calculateDisplayCutoutForRotation(di.rotation); - dc.getDisplayPolicy().getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, - cutout, outInsets); + outInsets.set(dc.getDisplayPolicy().getDecorInsetsInfo( + di.rotation, di.logicalWidth, di.logicalHeight).mConfigInsets); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index b601cc5897e2..65db35971026 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2511,6 +2511,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWinAnimator.mSurfaceController, Debug.getCallers(5)); + final DisplayContent displayContent = getDisplayContent(); final long origId = Binder.clearCallingIdentity(); try { @@ -2565,7 +2566,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // Set up a replacement input channel since the app is now dead. // We need to catch tapping on the dead window to restart the app. openInputChannel(null); - getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/); + displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/); return; } @@ -2573,7 +2574,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // usually unnoticeable (e.g. covered by rotation animation) and the animation // bounds could be inconsistent, such as depending on when the window applies // its draw transaction with new rotation. - final boolean allowExitAnimation = !getDisplayContent().inTransition() + final boolean allowExitAnimation = !displayContent.inTransition() // There will be a new window so the exit animation may not be visible or // look weird if its orientation is changed. && !inRelaunchingActivity(); @@ -2623,18 +2624,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } removeImmediately(); - boolean sentNewConfig = false; - if (wasVisible) { - // Removing a visible window will effect the computed orientation - // So just update orientation if needed. - final DisplayContent displayContent = getDisplayContent(); - if (displayContent.updateOrientation()) { - displayContent.sendNewConfiguration(); - sentNewConfig = true; - } - } - if (!sentNewConfig && providesNonDecorInsets()) { - getDisplayContent().sendNewConfiguration(); + // Removing a visible window may affect the display orientation so just update it if + // needed. Also recompute configuration if it provides screen decor insets. + if ((wasVisible && displayContent.updateOrientation()) + || displayContent.getDisplayPolicy().updateDecorInsetsInfoIfNeeded(this)) { + displayContent.sendNewConfiguration(); } mWmService.updateFocusedWindowLocked(isFocused() ? UPDATE_FOCUS_REMOVING_FOCUS diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index eb61a9ce57a5..bbd7695fc8cd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -158,7 +158,6 @@ import androidx.test.filters.MediumTest; import com.android.internal.R; import com.android.server.wm.ActivityRecord.State; -import com.android.server.wm.utils.WmDisplayCutout; import org.junit.Assert; import org.junit.Before; @@ -552,9 +551,9 @@ public class ActivityRecordTests extends WindowTestsBase { final Rect insets = new Rect(); final DisplayInfo displayInfo = task.mDisplayContent.getDisplayInfo(); final DisplayPolicy policy = task.mDisplayContent.getDisplayPolicy(); - policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth, - displayInfo.logicalHeight, WmDisplayCutout.NO_CUTOUT, insets); - policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation); + + insets.set(policy.getDecorInsetsInfo(displayInfo.rotation, displayInfo.logicalWidth, + displayInfo.logicalHeight).mConfigInsets); Task.intersectWithInsetsIfFits(stableRect, stableRect, insets); final boolean isScreenPortrait = stableRect.width() <= stableRect.height(); @@ -594,9 +593,8 @@ public class ActivityRecordTests extends WindowTestsBase { final Rect insets = new Rect(); final DisplayInfo displayInfo = rootTask.mDisplayContent.getDisplayInfo(); final DisplayPolicy policy = rootTask.mDisplayContent.getDisplayPolicy(); - policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth, - displayInfo.logicalHeight, WmDisplayCutout.NO_CUTOUT, insets); - policy.convertNonDecorInsetsToStableInsets(insets, displayInfo.rotation); + insets.set(policy.getDecorInsetsInfo(displayInfo.rotation, displayInfo.logicalWidth, + displayInfo.logicalHeight).mConfigInsets); Task.intersectWithInsetsIfFits(stableRect, stableRect, insets); final boolean isScreenPortrait = stableRect.width() <= stableRect.height(); @@ -2988,31 +2986,27 @@ public class ActivityRecordTests extends WindowTestsBase { } @Test - public void testCloseToSquareFixedOrientationPortrait() { + public void testCloseToSquareFixedOrientation() { // create a square display final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000) .setSystemDecorations(true).build(); + // Add a decor insets provider window. + final WindowState navbar = createNavBarWithProvidedInsets(squareDisplay); + squareDisplay.getDisplayPolicy().updateDecorInsetsInfoIfNeeded(navbar); final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); // create a fixed portrait activity - final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task) + ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT).build(); - // check that both the configuration and app bounds are portrait + // The available space could be landscape because of decor insets, but the configuration + // should still respect the requested portrait orientation. assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation); assertTrue(activity.getConfiguration().windowConfiguration.getAppBounds().width() <= activity.getConfiguration().windowConfiguration.getAppBounds().height()); - } - - @Test - public void testCloseToSquareFixedOrientationLandscape() { - // create a square display - final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000) - .setSystemDecorations(true).build(); - final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); // create a fixed landscape activity - final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task) + activity = new ActivityBuilder(mAtm).setTask(task) .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE).build(); // check that both the configuration and app bounds are landscape diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java index a001eda2f86e..e298d5114639 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java @@ -25,13 +25,10 @@ import static org.hamcrest.Matchers.equalTo; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; -import android.util.Pair; import android.view.DisplayInfo; import androidx.test.filters.SmallTest; -import com.android.server.wm.utils.WmDisplayCutout; - import org.junit.Rule; import org.junit.Test; import org.junit.rules.ErrorCollector; @@ -49,8 +46,7 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void portrait() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_0, false /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_0, false /* withCutout */); verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT); @@ -59,8 +55,7 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void portrait_withCutout() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_0, true /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_0, true /* withCutout */); verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); verifyNonDecorInsets(di, 0, DISPLAY_CUTOUT_HEIGHT, 0, NAV_BAR_HEIGHT); @@ -69,8 +64,7 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void landscape() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_90, false /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_90, false /* withCutout */); if (mDisplayPolicy.navigationBarCanMove()) { verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); @@ -85,8 +79,7 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void landscape_withCutout() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_90, true /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_90, true /* withCutout */); if (mDisplayPolicy.navigationBarCanMove()) { verifyStableInsets(di, DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); @@ -101,8 +94,7 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void seascape() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_270, false /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_270, false /* withCutout */); if (mDisplayPolicy.navigationBarCanMove()) { verifyStableInsets(di, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0); @@ -117,8 +109,7 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void seascape_withCutout() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_270, true /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_270, true /* withCutout */); if (mDisplayPolicy.navigationBarCanMove()) { verifyStableInsets(di, NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0); @@ -133,8 +124,7 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void upsideDown() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_180, false /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_180, false /* withCutout */); verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT); @@ -143,34 +133,32 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { @Test public void upsideDown_withCutout() { - final Pair<DisplayInfo, WmDisplayCutout> di = - displayInfoForRotation(ROTATION_180, true /* withCutout */); + final DisplayInfo di = displayInfoForRotation(ROTATION_180, true /* withCutout */); verifyStableInsets(di, 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT + DISPLAY_CUTOUT_HEIGHT); verifyNonDecorInsets(di, 0, 0, 0, NAV_BAR_HEIGHT + DISPLAY_CUTOUT_HEIGHT); verifyConsistency(di); } - private void verifyStableInsets(Pair<DisplayInfo, WmDisplayCutout> diPair, int left, int top, + private void verifyStableInsets(DisplayInfo di, int left, int top, int right, int bottom) { - mErrorCollector.checkThat("stableInsets", getStableInsetsLw(diPair.first, diPair.second), + mErrorCollector.checkThat("stableInsets", getStableInsets(di), equalTo(new Rect(left, top, right, bottom))); } - private void verifyNonDecorInsets(Pair<DisplayInfo, WmDisplayCutout> diPair, int left, int top, + private void verifyNonDecorInsets(DisplayInfo di, int left, int top, int right, int bottom) { mErrorCollector.checkThat("nonDecorInsets", - getNonDecorInsetsLw(diPair.first, diPair.second), equalTo(new Rect( - left, top, right, bottom))); + getNonDecorInsets(di), equalTo(new Rect(left, top, right, bottom))); } - private void verifyConsistency(Pair<DisplayInfo, WmDisplayCutout> diPair) { - final DisplayInfo di = diPair.first; - final WmDisplayCutout cutout = diPair.second; - verifyConsistency("configDisplay", di, getStableInsetsLw(di, cutout), - getConfigDisplayWidth(di, cutout), getConfigDisplayHeight(di, cutout)); - verifyConsistency("nonDecorDisplay", di, getNonDecorInsetsLw(di, cutout), - getNonDecorDisplayWidth(di, cutout), getNonDecorDisplayHeight(di, cutout)); + private void verifyConsistency(DisplayInfo di) { + final DisplayPolicy.DecorInsets.Info info = mDisplayPolicy.getDecorInsetsInfo( + di.rotation, di.logicalWidth, di.logicalHeight); + verifyConsistency("configDisplay", di, info.mConfigInsets, + info.mConfigFrame.width(), info.mConfigFrame.height()); + verifyConsistency("nonDecorDisplay", di, info.mNonDecorInsets, + info.mNonDecorFrame.width(), info.mNonDecorFrame.height()); } private void verifyConsistency(String what, DisplayInfo di, Rect insets, int width, @@ -181,42 +169,18 @@ public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase { equalTo(di.logicalHeight - insets.top - insets.bottom)); } - private Rect getStableInsetsLw(DisplayInfo di, WmDisplayCutout cutout) { - Rect result = new Rect(); - mDisplayPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, - cutout, result); - return result; - } - - private Rect getNonDecorInsetsLw(DisplayInfo di, WmDisplayCutout cutout) { - Rect result = new Rect(); - mDisplayPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, - cutout, result); - return result; - } - - private int getNonDecorDisplayWidth(DisplayInfo di, WmDisplayCutout cutout) { - return mDisplayPolicy.getNonDecorDisplayFrame(di.logicalWidth, di.logicalHeight, - di.rotation, cutout).width(); - } - - private int getNonDecorDisplayHeight(DisplayInfo di, WmDisplayCutout cutout) { - return mDisplayPolicy.getNonDecorDisplayFrame(di.logicalWidth, di.logicalHeight, - di.rotation, cutout).height(); - } - - private int getConfigDisplayWidth(DisplayInfo di, WmDisplayCutout cutout) { - return mDisplayPolicy.getConfigDisplaySize(di.logicalWidth, di.logicalHeight, - di.rotation, cutout).x; + private Rect getStableInsets(DisplayInfo di) { + return mDisplayPolicy.getDecorInsetsInfo( + di.rotation, di.logicalWidth, di.logicalHeight).mConfigInsets; } - private int getConfigDisplayHeight(DisplayInfo di, WmDisplayCutout cutout) { - return mDisplayPolicy.getConfigDisplaySize(di.logicalWidth, di.logicalHeight, - di.rotation, cutout).y; + private Rect getNonDecorInsets(DisplayInfo di) { + return mDisplayPolicy.getDecorInsetsInfo( + di.rotation, di.logicalWidth, di.logicalHeight).mNonDecorInsets; } - private static Pair<DisplayInfo, WmDisplayCutout> displayInfoForRotation(int rotation, - boolean withDisplayCutout) { - return displayInfoAndCutoutForRotation(rotation, withDisplayCutout, false); + private DisplayInfo displayInfoForRotation(int rotation, boolean withDisplayCutout) { + return displayInfoAndCutoutForRotation( + rotation, withDisplayCutout, false /* isLongEdgeCutout */); } } 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 34575ae2fe46..6951fef87416 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -41,7 +41,6 @@ import static org.testng.Assert.expectThrows; import android.graphics.Insets; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; -import android.util.Pair; import android.view.DisplayInfo; import android.view.InsetsFrameProvider; import android.view.InsetsState; @@ -50,8 +49,6 @@ import android.view.RoundedCorners; import androidx.test.filters.SmallTest; -import com.android.server.wm.utils.WmDisplayCutout; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -123,7 +120,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { private void updateDisplayFrames() { mFrames = createDisplayFrames( mDisplayContent.getInsetsStateController().getRawInsetsState()); - mDisplayBounds.set(0, 0, mFrames.mDisplayWidth, mFrames.mDisplayHeight); + mDisplayBounds.set(0, 0, mFrames.mWidth, mFrames.mHeight); mDisplayContent.mDisplayFrames = mFrames; mDisplayContent.setBounds(mDisplayBounds); mDisplayPolicy.layoutWindowLw(mNavBarWindow, null, mFrames); @@ -131,13 +128,13 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { } private DisplayFrames createDisplayFrames(InsetsState insetsState) { - final Pair<DisplayInfo, WmDisplayCutout> info = displayInfoAndCutoutForRotation(mRotation, + final DisplayInfo info = displayInfoAndCutoutForRotation(mRotation, mHasDisplayCutout, mIsLongEdgeDisplayCutout); final RoundedCorners roundedCorners = mHasRoundedCorners ? mDisplayContent.calculateRoundedCornersForRotation(mRotation) : RoundedCorners.NO_ROUNDED_CORNERS; - return new DisplayFrames(mDisplayContent.getDisplayId(), - insetsState, info.first, info.second, roundedCorners, new PrivacyIndicatorBounds()); + return new DisplayFrames(insetsState, info, + info.displayCutout, roundedCorners, new PrivacyIndicatorBounds()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 8f2e9b4c6ff6..e00296f4d801 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.view.DisplayCutout.NO_CUTOUT; import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; @@ -35,13 +36,12 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BA import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; -import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; -import static com.android.server.wm.utils.WmDisplayCutout.NO_CUTOUT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -286,10 +286,18 @@ public class DisplayPolicyTests extends WindowTestsBase { DisplayPolicy.isOverlappingWithNavBar(targetWin)); } - private WindowState createNavigationBarWindow() { - final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar"); - win.mHasSurface = true; - return win; + @Test + public void testUpdateDisplayConfigurationByDecor() { + final WindowState navbar = createNavBarWithProvidedInsets(mDisplayContent); + final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); + final DisplayInfo di = mDisplayContent.getDisplayInfo(); + final int prevScreenHeightDp = mDisplayContent.getConfiguration().screenHeightDp; + assertTrue(displayPolicy.updateDecorInsetsInfoIfNeeded(navbar)); + assertEquals(NAV_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation, + di.logicalWidth, di.logicalHeight).mConfigInsets.bottom); + mDisplayContent.sendNewConfiguration(); + assertNotEquals(prevScreenHeightDp, mDisplayContent.getConfiguration().screenHeightDp); + assertFalse(displayPolicy.updateDecorInsetsInfoIfNeeded(navbar)); } @UseTestDisplay(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD }) @@ -307,7 +315,7 @@ public class DisplayPolicyTests extends WindowTestsBase { mNavBarWindow.getControllableInsetProvider().setServerVisible(true); final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState(); mImeWindow.mAboveInsetsState.set(state); - mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(), + mDisplayContent.mDisplayFrames = new DisplayFrames( state, displayInfo, NO_CUTOUT, NO_ROUNDED_CORNERS, new PrivacyIndicatorBounds()); mDisplayContent.setInputMethodWindowLocked(mImeWindow); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java index 97b1c91d156a..fe890d56cbac 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java @@ -30,25 +30,14 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates; import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.anyInt; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.pm.PackageManager; -import android.content.res.Resources; import android.graphics.Matrix; import android.graphics.RectF; import android.os.Binder; -import android.os.IBinder; -import android.testing.TestableResources; -import android.util.Pair; import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.WindowManagerGlobal; -import com.android.internal.R; -import com.android.server.wm.utils.WmDisplayCutout; - import org.junit.Before; public class DisplayPolicyTestsBase extends WindowTestsBase { @@ -69,23 +58,8 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { mDisplayPolicy = mDisplayContent.getDisplayPolicy(); spyOn(mDisplayPolicy); - - final TestContextWrapper context = new TestContextWrapper( - mDisplayPolicy.getContext(), mDisplayPolicy.getCurrentUserResources()); - final TestableResources resources = context.getResourceMocker(); - resources.addOverride(R.dimen.navigation_bar_height, NAV_BAR_HEIGHT); - resources.addOverride(R.dimen.navigation_bar_height_landscape, NAV_BAR_HEIGHT); - resources.addOverride(R.dimen.navigation_bar_width, NAV_BAR_HEIGHT); - resources.addOverride(R.dimen.navigation_bar_frame_height_landscape, NAV_BAR_HEIGHT); - resources.addOverride(R.dimen.navigation_bar_frame_height, NAV_BAR_HEIGHT); - doReturn(STATUS_BAR_HEIGHT).when(mDisplayPolicy).getStatusBarHeightForRotation(anyInt()); - doReturn(resources.getResources()).when(mDisplayPolicy).getCurrentUserResources(); doReturn(true).when(mDisplayPolicy).hasNavigationBar(); doReturn(true).when(mDisplayPolicy).hasStatusBar(); - - mDisplayContent.getDisplayRotation().configure(DISPLAY_WIDTH, DISPLAY_HEIGHT); - mDisplayPolicy.onConfigurationChanged(); - addWindow(mStatusBarWindow); addWindow(mNavBarWindow); @@ -101,24 +75,20 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { win.mHasSurface = true; } - static Pair<DisplayInfo, WmDisplayCutout> displayInfoAndCutoutForRotation(int rotation, - boolean withDisplayCutout, boolean isLongEdgeCutout) { - final DisplayInfo info = new DisplayInfo(); - WmDisplayCutout cutout = WmDisplayCutout.NO_CUTOUT; - + DisplayInfo displayInfoAndCutoutForRotation(int rotation, boolean withDisplayCutout, + boolean isLongEdgeCutout) { + final DisplayInfo info = mDisplayContent.getDisplayInfo(); final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270; info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH; info.logicalHeight = flippedDimensions ? DISPLAY_WIDTH : DISPLAY_HEIGHT; info.rotation = rotation; - if (withDisplayCutout) { - cutout = WmDisplayCutout.computeSafeInsets( - displayCutoutForRotation(rotation, isLongEdgeCutout), info.logicalWidth, - info.logicalHeight); - info.displayCutout = cutout.getDisplayCutout(); - } else { - info.displayCutout = null; - } - return Pair.create(info, cutout); + mDisplayContent.mInitialDisplayCutout = withDisplayCutout + ? displayCutoutForRotation(ROTATION_0, isLongEdgeCutout) + : DisplayCutout.NO_CUTOUT; + info.displayCutout = mDisplayContent.calculateDisplayCutoutForRotation(rotation); + mDisplayContent.updateBaseDisplayMetrics(DISPLAY_WIDTH, DISPLAY_HEIGHT, + info.logicalDensityDpi, info.physicalXDpi, info.physicalYDpi); + return info; } private static DisplayCutout displayCutoutForRotation(int rotation, boolean isLongEdgeCutout) { @@ -152,33 +122,4 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { return DisplayCutout.fromBoundingRect((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom, pos); } - - static class TestContextWrapper extends ContextWrapper { - private final TestableResources mResourceMocker; - - TestContextWrapper(Context targetContext, Resources targetResources) { - super(targetContext); - mResourceMocker = new TestableResources(targetResources); - } - - @Override - public int checkPermission(String permission, int pid, int uid) { - return PackageManager.PERMISSION_GRANTED; - } - - @Override - public int checkPermission(String permission, int pid, int uid, IBinder callerToken) { - return PackageManager.PERMISSION_GRANTED; - } - - @Override - public Resources getResources() { - return mResourceMocker.getResources(); - } - - TestableResources getResourceMocker() { - return mResourceMocker; - } - } - } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java index 892b5f9d6753..89f71110f3c2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java @@ -20,6 +20,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.view.DisplayCutout.NO_CUTOUT; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DISABLED; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_ENABLED; @@ -68,7 +69,6 @@ import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.policy.WindowManagerPolicy; import com.android.server.statusbar.StatusBarManagerInternal; -import com.android.server.wm.utils.WmDisplayCutout; import org.junit.After; import org.junit.AfterClass; @@ -1008,7 +1008,7 @@ public class DisplayRotationTests { mMockDisplayContent = mock(DisplayContent.class); mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay; when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt())) - .thenReturn(WmDisplayCutout.NO_CUTOUT); + .thenReturn(NO_CUTOUT); when(mMockDisplayContent.getDefaultTaskDisplayArea()) .thenReturn(mock(TaskDisplayArea.class)); when(mMockDisplayContent.getWindowConfiguration()) 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 f6ffa91c58d4..2f1cc2034bed 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -3133,8 +3133,8 @@ public class SizeCompatTests extends WindowTestsBase { } private static void resizeDisplay(DisplayContent displayContent, int width, int height) { - displayContent.mBaseDisplayWidth = width; - displayContent.mBaseDisplayHeight = height; + displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity, + displayContent.mBaseDisplayPhysicalXDpi, displayContent.mBaseDisplayPhysicalYDpi); final Configuration c = new Configuration(); displayContent.computeScreenConfiguration(c); displayContent.onRequestedOverrideConfigurationChanged(c); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index f4323db2ceec..f3227799f913 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -36,7 +36,6 @@ import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_90; import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; @@ -692,12 +691,9 @@ public class TaskTests extends WindowTestsBase { // Setup the display with a top stable inset. The later assertion will ensure the inset is // excluded from screenHeightDp. final int statusBarHeight = 100; - final DisplayPolicy policy = display.getDisplayPolicy(); - doAnswer(invocationOnMock -> { - final Rect insets = invocationOnMock.<Rect>getArgument(0); - insets.top = statusBarHeight; - return null; - }).when(policy).convertNonDecorInsetsToStableInsets(any(), eq(ROTATION_0)); + final DisplayInfo di = display.getDisplayInfo(); + display.getDisplayPolicy().getDecorInsetsInfo(di.rotation, + di.logicalWidth, di.logicalHeight).mConfigInsets.top = statusBarHeight; // Without limiting to be inside the parent bounds, the out screen size should keep relative // to the input bounds. diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java index f5304d00faab..aa3ca18073c3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java @@ -18,13 +18,6 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; -import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT; -import static android.view.InsetsState.ITYPE_CLIMATE_BAR; -import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT; -import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; -import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT; -import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT; import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; @@ -33,7 +26,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; 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.spyOn; import android.annotation.Nullable; @@ -47,7 +39,6 @@ import android.util.DisplayMetrics; import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayInfo; -import android.view.WindowInsets; import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry; @@ -209,26 +200,6 @@ class TestDisplayContent extends DisplayContent { doReturn(true).when(newDisplay).supportsSystemDecorations(); doReturn(true).when(displayPolicy).hasNavigationBar(); doReturn(NAV_BAR_BOTTOM).when(displayPolicy).navigationBarPosition(anyInt()); - doReturn(Insets.of(0, 0, 0, 20)).when(displayPolicy).getInsets(any(), - eq(WindowInsets.Type.displayCutout() | WindowInsets.Type.navigationBars())); - doReturn(Insets.of(0, 20, 0, 20)).when(displayPolicy).getInsets(any(), - eq(WindowInsets.Type.displayCutout() | WindowInsets.Type.navigationBars() - | WindowInsets.Type.statusBars())); - final int[] nonDecorTypes = new int[]{ - ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT, - ITYPE_BOTTOM_DISPLAY_CUTOUT, ITYPE_LEFT_DISPLAY_CUTOUT, ITYPE_NAVIGATION_BAR - }; - doReturn(Insets.of(0, 0, 0, 20)).when(displayPolicy).getInsetsWithInternalTypes( - any(), - eq(nonDecorTypes)); - final int[] stableTypes = new int[]{ - ITYPE_TOP_DISPLAY_CUTOUT, ITYPE_RIGHT_DISPLAY_CUTOUT, - ITYPE_BOTTOM_DISPLAY_CUTOUT, ITYPE_LEFT_DISPLAY_CUTOUT, - ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR, ITYPE_CLIMATE_BAR - }; - doReturn(Insets.of(0, 20, 0, 20)).when(displayPolicy).getInsetsWithInternalTypes( - any(), - eq(stableTypes)); } else { doReturn(false).when(displayPolicy).hasNavigationBar(); doReturn(false).when(displayPolicy).hasStatusBar(); @@ -241,11 +212,6 @@ class TestDisplayContent extends DisplayContent { displayPolicy.finishScreenTurningOn(); if (mStatusBarHeight > 0) { doReturn(true).when(displayPolicy).hasStatusBar(); - doAnswer(invocation -> { - Rect inOutInsets = (Rect) invocation.getArgument(0); - inOutInsets.top = mStatusBarHeight; - return null; - }).when(displayPolicy).convertNonDecorInsetsToStableInsets(any(), anyInt()); } Configuration c = new Configuration(); newDisplay.computeScreenConfiguration(c); diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java index 82887135c73d..63335086859d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java @@ -52,6 +52,7 @@ import android.graphics.Rect; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; import android.view.InsetsState; @@ -63,8 +64,6 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; -import com.android.server.wm.utils.WmDisplayCutout; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -164,8 +163,8 @@ public class WallpaperControllerTests extends WindowTestsBase { // Apply the fixed transform Configuration config = new Configuration(); final DisplayInfo info = dc.computeScreenConfiguration(config, Surface.ROTATION_0); - final WmDisplayCutout cutout = dc.calculateDisplayCutoutForRotation(Surface.ROTATION_0); - final DisplayFrames displayFrames = new DisplayFrames(dc.getDisplayId(), new InsetsState(), + final DisplayCutout cutout = dc.calculateDisplayCutoutForRotation(Surface.ROTATION_0); + final DisplayFrames displayFrames = new DisplayFrames(new InsetsState(), info, cutout, RoundedCorners.NO_ROUNDED_CORNERS, new PrivacyIndicatorBounds()); wallpaperWindow.mToken.applyFixedRotationTransform(info, displayFrames, config); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 77e12f40f72e..b6373b4c439f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -26,6 +26,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.os.Process.SYSTEM_UID; +import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.View.VISIBLE; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; @@ -69,6 +70,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; +import android.graphics.Insets; import android.graphics.Rect; import android.hardware.HardwareBuffer; import android.hardware.display.DisplayManager; @@ -84,6 +86,7 @@ import android.view.DisplayInfo; import android.view.Gravity; import android.view.IDisplayWindowInsetsController; import android.view.IWindow; +import android.view.InsetsFrameProvider; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsVisibilities; @@ -417,6 +420,15 @@ class WindowTestsBase extends SystemServiceTestsBase { true /* ownerCanManageAppTokens */); } + WindowState createNavBarWithProvidedInsets(DisplayContent dc) { + final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, dc, "navbar"); + navbar.mAttrs.providedInsets = new InsetsFrameProvider[] { + new InsetsFrameProvider(ITYPE_NAVIGATION_BAR, Insets.of(0, 0, 0, NAV_BAR_HEIGHT)) + }; + dc.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs); + return navbar; + } + WindowState createAppWindow(Task task, int type, String name) { final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent()); task.addChild(activity, 0); |