diff options
25 files changed, 355 insertions, 1124 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index ba52ccae153d..ca0eda5eec0e 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -15483,6 +15483,8 @@ package android.graphics { method @NonNull public String flattenToString(); method public int height(); method public void inset(int, int); + method public void inset(@NonNull android.graphics.Insets); + method public void inset(int, int, int, int); method @CheckResult public boolean intersect(int, int, int, int); method @CheckResult public boolean intersect(@NonNull android.graphics.Rect); method public boolean intersects(int, int, int, int); diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index ac29f2eb5c0b..41b2fb4d2097 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -238,6 +238,22 @@ public class InsetsState implements Parcelable { (legacySystemUiFlags & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0); } + public Rect calculateInsets(Rect frame, @InsetsType int types, boolean ignoreVisibility) { + Insets insets = Insets.NONE; + for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { + InsetsSource source = mSources[type]; + if (source == null) { + continue; + } + int publicType = InsetsState.toPublicType(type); + if ((publicType & types) == 0) { + continue; + } + insets = Insets.max(source.calculateInsets(frame, ignoreVisibility), insets); + } + return insets.toRect(); + } + public Rect calculateVisibleInsets(Rect frame, @SoftInputModeFlags int softInputMode) { Insets insets = Insets.NONE; for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index c0770063beea..9c6e900ffbe6 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1023,6 +1023,15 @@ public final class ViewRootImpl implements ViewParent, } mForceDecorViewVisibility = (mWindowAttributes.privateFlags & PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0; + + if (mView instanceof RootViewSurfaceTaker) { + PendingInsetsController pendingInsetsController = + ((RootViewSurfaceTaker) mView).providePendingInsetsController(); + if (pendingInsetsController != null) { + pendingInsetsController.replayAndAttach(mInsetsController); + } + } + try { mOrigWindowType = mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; @@ -1160,14 +1169,6 @@ public final class ViewRootImpl implements ViewParent, mFirstInputStage = nativePreImeStage; mFirstPostImeInputStage = earlyPostImeStage; mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix; - - if (mView instanceof RootViewSurfaceTaker) { - PendingInsetsController pendingInsetsController = - ((RootViewSurfaceTaker) mView).providePendingInsetsController(); - if (pendingInsetsController != null) { - pendingInsetsController.replayAndAttach(mInsetsController); - } - } } } } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 8b0cf3bb86dc..2168dd01089d 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -1344,6 +1344,9 @@ public final class WindowInsets { if ((types & NAVIGATION_BARS) != 0) { result.append("navigationBars |"); } + if ((types & CAPTION_BAR) != 0) { + result.append("captionBar |"); + } if ((types & IME) != 0) { result.append("ime |"); } diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index ce52a352e10b..32a40d9a285b 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -239,9 +239,9 @@ message DisplayAreaChildProto { message DisplayFramesProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; - optional .android.graphics.RectProto stable_bounds = 1; - optional .android.graphics.RectProto dock = 2; - optional .android.graphics.RectProto current = 3; + optional .android.graphics.RectProto stable_bounds = 1 [deprecated=true]; + optional .android.graphics.RectProto dock = 2 [deprecated=true]; + optional .android.graphics.RectProto current = 3 [deprecated=true]; } message DisplayRotationProto { @@ -499,19 +499,19 @@ message WindowFramesProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; optional .android.graphics.RectProto containing_frame = 1; - optional .android.graphics.RectProto content_frame = 2; - optional .android.graphics.RectProto decor_frame = 3; + optional .android.graphics.RectProto content_frame = 2 [deprecated=true]; + optional .android.graphics.RectProto decor_frame = 3 [deprecated=true]; optional .android.graphics.RectProto display_frame = 4; optional .android.graphics.RectProto frame = 5; optional .android.graphics.RectProto outset_frame = 6; optional .android.graphics.RectProto overscan_frame = 7 [deprecated=true]; optional .android.graphics.RectProto parent_frame = 8; - optional .android.graphics.RectProto visible_frame = 9; + optional .android.graphics.RectProto visible_frame = 9 [deprecated=true]; optional .android.view.DisplayCutoutProto cutout = 10; - optional .android.graphics.RectProto content_insets = 11; + optional .android.graphics.RectProto content_insets = 11 [deprecated=true]; optional .android.graphics.RectProto overscan_insets = 12 [deprecated=true]; - optional .android.graphics.RectProto visible_insets = 13; - optional .android.graphics.RectProto stable_insets = 14; + optional .android.graphics.RectProto visible_insets = 13 [deprecated=true]; + optional .android.graphics.RectProto stable_insets = 14 [deprecated=true]; optional .android.graphics.RectProto outsets = 15; } diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 081b851d1333..87ca9607dbce 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -433,10 +433,10 @@ public final class Rect implements Parcelable { /** * Insets the rectangle on all sides specified by the dimensions of {@code insets}. - * @hide + * * @param insets The insets to inset the rect by. */ - public void inset(Insets insets) { + public void inset(@NonNull Insets insets) { left += insets.left; top += insets.top; right -= insets.right; @@ -445,7 +445,7 @@ public final class Rect implements Parcelable { /** * Insets the rectangle on all sides specified by the insets. - * @hide + * * @param left The amount to add from the rectangle's left * @param top The amount to add from the rectangle's top * @param right The amount to subtract from the rectangle's right diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 98c38f96e5ce..bd8c2ba6a9bf 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -288,6 +288,7 @@ import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; +import android.view.WindowInsets.Type; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.animation.Animation; @@ -4228,7 +4229,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Force add to mResizingWindows, so that we are guaranteed to get // another reportDrawn callback. - w.resetLastContentInsets(); + w.forceReportingResized(); } }, true /* traverseTopToBottom */); } @@ -6192,9 +6193,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // destination of the thumbnail header animation. If this is a full screen // window scenario, we use the whole display as the target. WindowState win = findMainWindow(); - final Rect appRect = win != null ? win.getContentFrame() : - new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight); - final Rect insets = win != null ? win.getContentInsets() : null; + Rect insets; + Rect appRect; + if (win != null) { + insets = win.getInsetsStateWithVisibilityOverride().calculateInsets( + win.getFrame(), Type.systemBars(), false /* ignoreVisibility */); + appRect = new Rect(win.getFrame()); + appRect.inset(insets); + } else { + insets = null; + appRect = new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight); + } final Configuration displayConfig = mDisplayContent.getConfiguration(); return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked( appRect, insets, thumbnailHeader, task, displayConfig.uiMode, @@ -7918,8 +7927,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (task == null || mainWindow == null) { return null; } - final Rect insets = new Rect(); - mainWindow.getContentInsets(insets); + final Rect insets = mainWindow.getInsetsStateWithVisibilityOverride().calculateInsets( + task.getBounds(), Type.systemBars(), false /* ignoreVisibility */); InsetUtils.addInsets(insets, getLetterboxInsets()); return new RemoteAnimationTarget(task.mTaskId, record.getMode(), diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 07c61d3dcea5..9118944b3334 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -51,6 +51,9 @@ import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.View.GONE; +import static android.view.WindowInsets.Type.displayCutout; +import static android.view.WindowInsets.Type.ime; +import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; @@ -756,7 +759,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (!w.getFrame().isEmpty()) { w.updateLastFrames(); } - w.updateLastInsetValues(); + w.onResizeHandled(); w.updateLocationInParentDisplayIfNeeded(); } @@ -2562,7 +2565,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } void getStableRect(Rect out) { - out.set(mDisplayFrames.mStable); + final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState(); + out.set(state.getDisplayFrame()); + out.inset(state.calculateInsets(out, systemBars(), true /* ignoreVisibility */)); } /** @@ -2690,12 +2695,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // If the task is freeformed, enlarge the area to account for outside // touch area for resize. mTmpRect.inset(-delta, -delta); - // Intersect with display content rect. If we have system decor (status bar/ + // Intersect with display content frame. If we have system decor (status bar/ // navigation bar), we want to exclude that from the tap detection. // Otherwise, if the app is partially placed under some system button (eg. // Recents, Home), pressing that button would cause a full series of // unwanted transfer focus/resume/pause, before we could go home. - mTmpRect.intersect(mDisplayFrames.mContent); + mTmpRect.inset(getInsetsStateController().getRawInsetsState().calculateInsets( + mTmpRect, systemBars() | ime(), false /* ignoreVisibility */)); } mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE); } @@ -2783,10 +2789,25 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp final WindowState imeWin = mInputMethodWindow; final boolean imeVisible = imeWin != null && imeWin.isVisible() && imeWin.isDisplayed(); - final int imeHeight = mDisplayFrames.getInputMethodWindowVisibleHeight(); + final int imeHeight = getInputMethodWindowVisibleHeight(); mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight); } + int getInputMethodWindowVisibleHeight() { + final InsetsState state = getInsetsStateController().getRawInsetsState(); + final InsetsSource imeSource = state.peekSource(ITYPE_IME); + if (imeSource == null || !imeSource.isVisible()) { + return 0; + } + final Rect imeFrame = imeSource.getVisibleFrame() != null + ? imeSource.getVisibleFrame() : imeSource.getFrame(); + final Rect dockFrame = mTmpRect; + dockFrame.set(state.getDisplayFrame()); + dockFrame.inset(state.calculateInsets(dockFrame, systemBars() | displayCutout(), + false /* ignoreVisibility */)); + return dockFrame.bottom - imeFrame.top; + } + void prepareFreezingTaskBounds() { forAllTaskDisplayAreas(TaskDisplayArea::prepareFreezingTaskBounds); } diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java index d67f3f967e66..7f3cb49d20e5 100644 --- a/services/core/java/com/android/server/wm/DisplayFrames.java +++ b/services/core/java/com/android/server/wm/DisplayFrames.java @@ -16,10 +16,6 @@ package com.android.server.wm; -import static com.android.server.wm.DisplayFramesProto.CURRENT; -import static com.android.server.wm.DisplayFramesProto.DOCK; -import static com.android.server.wm.DisplayFramesProto.STABLE_BOUNDS; - import android.annotation.NonNull; import android.graphics.Rect; import android.util.proto.ProtoOutputStream; @@ -43,51 +39,6 @@ public class DisplayFrames { */ public final Rect mUnrestricted = new Rect(); - /** - * The current size of the screen; these may be different than (0,0)-(dw,dh) if the status bar - * can't be hidden; in that case it effectively carves out that area of the display from all - * other windows. - */ - public final Rect mRestricted = new Rect(); - - /** - * During layout, the current screen borders accounting for any currently visible system UI - * elements. - */ - public final Rect mSystem = new Rect(); - - /** For applications requesting stable content insets, these are them. */ - public final Rect mStable = new Rect(); - - /** - * For applications requesting stable content insets but have also set the fullscreen window - * flag, these are the stable dimensions without the status bar. - */ - public final Rect mStableFullscreen = new Rect(); - - /** - * During layout, the current screen borders with all outer decoration (status bar, input method - * dock) accounted for. - */ - public final Rect mCurrent = new Rect(); - - /** - * During layout, the frame in which content should be displayed to the user, accounting for all - * screen decoration except for any space they deem as available for other content. This is - * usually the same as mCurrent*, but may be larger if the screen decor has supplied content - * insets. - */ - public final Rect mContent = new Rect(); - - /** - * During layout, the frame in which voice content should be displayed to the user, accounting - * for all screen decoration except for any space they deem as available for other content. - */ - public final Rect mVoiceContent = new Rect(); - - /** During layout, the current screen borders along which input method windows are placed. */ - public final Rect mDock = new Rect(); - /** The display cutout used for layout (after rotation) */ @NonNull public WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT; @@ -118,15 +69,6 @@ public class DisplayFrames { public void onBeginLayout() { mUnrestricted.set(0, 0, mDisplayWidth, mDisplayHeight); - mRestricted.set(mUnrestricted); - mSystem.set(mUnrestricted); - mDock.set(mUnrestricted); - mContent.set(mUnrestricted); - mVoiceContent.set(mUnrestricted); - mStable.set(mUnrestricted); - mStableFullscreen.set(mUnrestricted); - mCurrent.set(mUnrestricted); - mDisplayCutout = mDisplayInfoCutout; mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); @@ -147,15 +89,8 @@ public class DisplayFrames { } } - public int getInputMethodWindowVisibleHeight() { - return mDock.bottom - mCurrent.bottom; - } - public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); - mStable.dumpDebug(proto, STABLE_BOUNDS); - mDock.dumpDebug(proto, DOCK); - mCurrent.dumpDebug(proto, CURRENT); proto.end(token); } @@ -163,14 +98,6 @@ public class DisplayFrames { pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight + " r=" + mRotation); final String myPrefix = prefix + " "; - dumpFrame(mStable, "mStable", myPrefix, pw); - dumpFrame(mStableFullscreen, "mStableFullscreen", myPrefix, pw); - dumpFrame(mDock, "mDock", myPrefix, pw); - dumpFrame(mCurrent, "mCurrent", myPrefix, pw); - dumpFrame(mSystem, "mSystem", myPrefix, pw); - dumpFrame(mContent, "mContent", myPrefix, pw); - dumpFrame(mVoiceContent, "mVoiceContent", myPrefix, pw); - dumpFrame(mRestricted, "mRestricted", myPrefix, pw); dumpFrame(mUnrestricted, "mUnrestricted", myPrefix, pw); pw.println(myPrefix + "mDisplayCutout=" + mDisplayCutout); } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index fc3fc4731e7d..11a436ec26c4 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -68,9 +68,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; -import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; 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; @@ -323,7 +320,6 @@ public class DisplayPolicy { private boolean mLastImmersiveMode; - private StatusBarManagerInternal mStatusBarInternal; private final BarController mStatusBarController; private final BarController mNavigationBarController; @@ -333,12 +329,6 @@ public class DisplayPolicy { private WindowState mSystemUiControllingWindow; - // The states of decor windows from the last layout. These are used to generate another display - // layout in different bounds but with the same states. - private boolean mLastNavVisible; - private boolean mLastNavTranslucent; - private boolean mLastNavAllowedHidden; - private int mLastDisableFlags; private int mLastAppearance; private int mLastFullscreenAppearance; @@ -1568,18 +1558,14 @@ public class DisplayPolicy { simulateLayoutDecorWindow(mNavigationBar, displayFrames, insetsState, simulatedWindowFrames, barContentFrames, contentFrame -> layoutNavigationBar(displayFrames, - mDisplayContent.getConfiguration().uiMode, mLastNavVisible, - mLastNavTranslucent, mLastNavAllowedHidden, - contentFrame)); + mDisplayContent.getConfiguration().uiMode, contentFrame)); } if (mStatusBar != null) { simulateLayoutDecorWindow(mStatusBar, displayFrames, insetsState, simulatedWindowFrames, barContentFrames, - contentFrame -> layoutStatusBar(displayFrames, mLastAppearance, - contentFrame)); + contentFrame -> layoutStatusBar(displayFrames, contentFrame)); } layoutScreenDecorWindows(displayFrames, simulatedWindowFrames); - postAdjustDisplayFrames(displayFrames); } /** @@ -1596,35 +1582,11 @@ public class DisplayPolicy { mSystemGestures.screenWidth = displayFrames.mUnrestricted.width(); mSystemGestures.screenHeight = displayFrames.mUnrestricted.height(); - // For purposes of putting out fake window up to steal focus, we will - // drive nav being hidden only by whether it is requested. - final int appearance = mLastAppearance; - final int behavior = mLastBehavior; - final InsetsSourceProvider provider = - mDisplayContent.getInsetsStateController().peekSourceProvider(ITYPE_NAVIGATION_BAR); - boolean navVisible = provider != null ? provider.isClientVisible() - : InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR); - boolean navTranslucent = (appearance & APPEARANCE_OPAQUE_NAVIGATION_BARS) == 0; - boolean immersive = (behavior & BEHAVIOR_SHOW_BARS_BY_SWIPE) != 0; - boolean immersiveSticky = (behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0; - boolean navAllowedHidden = immersive || immersiveSticky; - navTranslucent &= !immersiveSticky; // transient trumps translucent - updateHideNavInputEventReceiver(); - // For purposes of positioning and showing the nav bar, if we have decided that it can't - // be hidden (because of the screen aspect ratio), then take that into account. - navVisible |= !canHideNavigationBar(); - - layoutNavigationBar(displayFrames, uiMode, navVisible, - navTranslucent, navAllowedHidden, null /* simulatedContentFrame */); - if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock); - layoutStatusBar(displayFrames, appearance, null /* simulatedContentFrame */); + layoutNavigationBar(displayFrames, uiMode, null /* simulatedContentFrame */); + layoutStatusBar(displayFrames, null /* simulatedContentFrame */); layoutScreenDecorWindows(displayFrames, null /* simulatedFrames */); - postAdjustDisplayFrames(displayFrames); - mLastNavVisible = navVisible; - mLastNavTranslucent = navTranslucent; - mLastNavAllowedHidden = navAllowedHidden; } void updateHideNavInputEventReceiver() { @@ -1679,26 +1641,6 @@ public class DisplayPolicy { state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(u.left, s.bottom, u.right, u.bottom); } - /** Enforces the last layout policy for display frames. */ - private void postAdjustDisplayFrames(DisplayFrames displayFrames) { - if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) { - // Make sure that the zone we're avoiding for the cutout is at least as tall as the - // status bar; otherwise fullscreen apps will end up cutting halfway into the status - // bar. - displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top, - displayFrames.mStable.top); - } - - // In case this is a virtual display, and the host display has insets that overlap this - // virtual display, apply the insets of the overlapped area onto the current and content - // frame of this virtual display. This let us layout windows in the virtual display as - // expected when the window needs to avoid overlap with the system windows. - // TODO: Generalize the forwarded insets, so that we can handle system windows other than - // IME. - displayFrames.mCurrent.inset(mForwardedInsets); - displayFrames.mContent.inset(mForwardedInsets); - } - /** * Layout the decor windows with {@link #PRIVATE_FLAG_IS_SCREEN_DECOR}. * @@ -1714,9 +1656,6 @@ public class DisplayPolicy { sTmpRect.setEmpty(); final int displayId = displayFrames.mDisplayId; - final Rect dockFrame = displayFrames.mDock; - final int displayHeight = displayFrames.mDisplayHeight; - final int displayWidth = displayFrames.mDisplayWidth; for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) { final WindowState w = mScreenDecorWindows.valueAt(i); @@ -1732,10 +1671,7 @@ public class DisplayPolicy { getRotatedWindowBounds(displayFrames, w, sTmpScreenDecorFrame); final WindowFrames windowFrames = w.getLayoutingWindowFrames(); windowFrames.setFrames(sTmpScreenDecorFrame /* parentFrame */, - sTmpScreenDecorFrame /* displayFrame */, - sTmpScreenDecorFrame /* contentFrame */, - sTmpScreenDecorFrame /* visibleFrame */, sTmpRect /* decorFrame */, - sTmpScreenDecorFrame /* stableFrame */); + sTmpScreenDecorFrame /* displayFrame */); try { w.computeFrame(displayFrames); } finally { @@ -1743,128 +1679,61 @@ public class DisplayPolicy { w.setSimulatedWindowFrames(null); } } - final Rect frame = windowFrames.mFrame; - - if (frame.left <= 0 && frame.top <= 0) { - // Docked at left or top. - if (frame.bottom >= displayHeight) { - // Docked left. - dockFrame.left = Math.max(frame.right, dockFrame.left); - } else if (frame.right >= displayWidth) { - // Docked top. - dockFrame.top = Math.max(frame.bottom, dockFrame.top); - } else { - Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w - + " not docked on left or top of display. frame=" + frame - + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight); - } - } else if (frame.right >= displayWidth && frame.bottom >= displayHeight) { - // Docked at right or bottom. - if (frame.top <= 0) { - // Docked right. - dockFrame.right = Math.min(frame.left, dockFrame.right); - } else if (frame.left <= 0) { - // Docked bottom. - dockFrame.bottom = Math.min(frame.top, dockFrame.bottom); - } else { - Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w - + " not docked on right or bottom" + " of display. frame=" + frame - + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight); - } - } else { - // Screen decor windows are required to be docked on one of the sides of the screen. - Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w - + " not docked on one of the sides of the display. frame=" + frame - + " displayWidth=" + displayWidth + " displayHeight=" + displayHeight); - } } - - displayFrames.mRestricted.set(dockFrame); - displayFrames.mCurrent.set(dockFrame); - displayFrames.mVoiceContent.set(dockFrame); - displayFrames.mSystem.set(dockFrame); - displayFrames.mContent.set(dockFrame); } - private void layoutStatusBar(DisplayFrames displayFrames, int appearance, - Rect simulatedContentFrame) { + private void layoutStatusBar(DisplayFrames displayFrames, Rect simulatedContentFrame) { // decide where the status bar goes ahead of time if (mStatusBar == null) { return; } // apply any status bar insets getRotatedWindowBounds(displayFrames, mStatusBar, sTmpStatusFrame); - sTmpRect.setEmpty(); final WindowFrames windowFrames = mStatusBar.getLayoutingWindowFrames(); windowFrames.setFrames(sTmpStatusFrame /* parentFrame */, - sTmpStatusFrame /* displayFrame */, sTmpStatusFrame /* contentFrame */, - sTmpStatusFrame /* visibleFrame */, sTmpRect /* decorFrame */, - sTmpStatusFrame /* stableFrame */); + sTmpStatusFrame /* displayFrame */); // Let the status bar determine its size. mStatusBar.computeFrame(displayFrames); // For layout, the status bar is always at the top with our fixed height. - displayFrames.mStable.top = displayFrames.mUnrestricted.top + int statusBarBottom = displayFrames.mUnrestricted.top + mStatusBarHeightForRotation[displayFrames.mRotation]; // Make sure the status bar covers the entire cutout height - displayFrames.mStable.top = Math.max(displayFrames.mStable.top, - displayFrames.mDisplayCutoutSafe.top); + statusBarBottom = Math.max(statusBarBottom, displayFrames.mDisplayCutoutSafe.top); + + if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) { + // Make sure that the zone we're avoiding for the cutout is at least as tall as the + // status bar; otherwise fullscreen apps will end up cutting halfway into the status + // bar. + displayFrames.mDisplayCutoutSafe.top = Math.max(displayFrames.mDisplayCutoutSafe.top, + statusBarBottom); + } // Tell the bar controller where the collapsed status bar content is. - sTmpRect.set(windowFrames.mContentFrame); + sTmpRect.set(windowFrames.mFrame); sTmpRect.intersect(displayFrames.mDisplayCutoutSafe); - sTmpRect.top = windowFrames.mContentFrame.top; // Ignore top display cutout inset - sTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size + sTmpRect.top = windowFrames.mFrame.top; // Ignore top display cutout inset + sTmpRect.bottom = statusBarBottom; // Use collapsed status bar size if (simulatedContentFrame != null) { simulatedContentFrame.set(sTmpRect); } else { mStatusBarController.setContentFrame(sTmpRect); } - - boolean statusBarTransient = - mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR); - boolean statusBarTranslucent = (appearance & APPEARANCE_OPAQUE_STATUS_BARS) == 0; - - // If the status bar is hidden, we don't want to cause windows behind it to scroll. - if (mStatusBar.isVisible() && !statusBarTransient) { - // Status bar may go away, so the screen area it occupies is available to apps but just - // covering them when the status bar is visible. - final Rect dockFrame = displayFrames.mDock; - dockFrame.top = displayFrames.mStable.top; - displayFrames.mContent.set(dockFrame); - displayFrames.mVoiceContent.set(dockFrame); - displayFrames.mCurrent.set(dockFrame); - - if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format( - "dock=%s content=%s cur=%s", dockFrame.toString(), - displayFrames.mContent.toString(), displayFrames.mCurrent.toString())); - - if (!statusBarTranslucent && !mStatusBar.isAnimatingLw()) { - - // If the opaque status bar is currently requested to be visible, and not in the - // process of animating on or off, then we can tell the app that it is covered by - // it. - displayFrames.mSystem.top = displayFrames.mStable.top; - } - } } - private void layoutNavigationBar(DisplayFrames displayFrames, int uiMode, boolean navVisible, - boolean navTranslucent, boolean navAllowedHidden, Rect simulatedContentFrame) { + private void layoutNavigationBar(DisplayFrames displayFrames, int uiMode, + Rect simulatedContentFrame) { if (mNavigationBar == null) { return; } final Rect navigationFrame = sTmpNavFrame; - boolean navBarTransient = - mDisplayContent.getInsetsPolicy().isTransient(ITYPE_NAVIGATION_BAR); // Force the navigation bar to its appropriate place and size. We need to do this directly, // instead of relying on it to bubble up from the nav bar, because this needs to change // atomically with screen rotations. final int rotation = displayFrames.mRotation; final int displayHeight = displayFrames.mDisplayHeight; final int displayWidth = displayFrames.mDisplayWidth; - final Rect dockFrame = displayFrames.mDock; final int navBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation); getRotatedWindowBounds(displayFrames, mNavigationBar, navigationFrame); @@ -1875,73 +1744,31 @@ public class DisplayPolicy { if (navBarPosition == NAV_BAR_BOTTOM) { // It's a system nav bar or a portrait screen; nav bar goes on bottom. - final int topNavBar = Math.min(cutoutSafeUnrestricted.bottom, navigationFrame.bottom) + navigationFrame.top = Math.min(cutoutSafeUnrestricted.bottom, navigationFrame.bottom) - getNavigationBarFrameHeight(rotation, uiMode); - final int top = mNavButtonForcedVisible ? topNavBar : - Math.min(cutoutSafeUnrestricted.bottom, navigationFrame.bottom) - - getNavigationBarHeight(rotation, uiMode); - navigationFrame.top = topNavBar; - displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top; - if (navVisible && !navBarTransient) { - dockFrame.bottom = displayFrames.mRestricted.bottom = top; - } - if (navVisible && !navTranslucent && !navAllowedHidden - && !mNavigationBar.isAnimatingLw()) { - // If the opaque nav bar is currently requested to be visible and not in the process - // of animating on or off, then we can tell the app that it is covered by it. - displayFrames.mSystem.bottom = top; - } } else if (navBarPosition == NAV_BAR_RIGHT) { // Landscape screen; nav bar goes to the right. - final int left = Math.min(cutoutSafeUnrestricted.right, navigationFrame.right) + navigationFrame.left = Math.min(cutoutSafeUnrestricted.right, navigationFrame.right) - getNavigationBarWidth(rotation, uiMode); - navigationFrame.left = left; - displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left; - if (navVisible && !navBarTransient) { - dockFrame.right = displayFrames.mRestricted.right = left; - } - if (navVisible && !navTranslucent && !navAllowedHidden - && !mNavigationBar.isAnimatingLw()) { - // If the nav bar is currently requested to be visible, and not in the process of - // animating on or off, then we can tell the app that it is covered by it. - displayFrames.mSystem.right = left; - } } else if (navBarPosition == NAV_BAR_LEFT) { // Seascape screen; nav bar goes to the left. - final int right = Math.max(cutoutSafeUnrestricted.left, navigationFrame.left) + navigationFrame.right = Math.max(cutoutSafeUnrestricted.left, navigationFrame.left) + getNavigationBarWidth(rotation, uiMode); - navigationFrame.right = right; - displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right; - if (navVisible && !navBarTransient) { - dockFrame.left = displayFrames.mRestricted.left = right; - } - if (navVisible && !navTranslucent && !navAllowedHidden - && !mNavigationBar.isAnimatingLw()) { - // If the nav bar is currently requested to be visible, and not in the process of - // animating on or off, then we can tell the app that it is covered by it. - displayFrames.mSystem.left = right; - } } - // Make sure the content and current rectangles are updated to account for the restrictions - // from the navigation bar. - displayFrames.mCurrent.set(dockFrame); - displayFrames.mVoiceContent.set(dockFrame); - displayFrames.mContent.set(dockFrame); - // And compute the final frame. - sTmpRect.setEmpty(); + // Compute the final frame. final WindowFrames windowFrames = mNavigationBar.getLayoutingWindowFrames(); windowFrames.setFrames(navigationFrame /* parentFrame */, - navigationFrame /* displayFrame */, - displayFrames.mDisplayCutoutSafe /* contentFrame */, - navigationFrame /* visibleFrame */, sTmpRect /* decorFrame */, - navigationFrame /* stableFrame */); + navigationFrame /* displayFrame */); mNavigationBar.computeFrame(displayFrames); + final Rect contentFrame = sTmpRect; + contentFrame.set(windowFrames.mFrame); + contentFrame.intersect(displayFrames.mDisplayCutoutSafe); if (simulatedContentFrame != null) { - simulatedContentFrame.set(windowFrames.mContentFrame); + simulatedContentFrame.set(contentFrame); } else { mNavigationBarPosition = navBarPosition; - mNavigationBarController.setContentFrame(windowFrames.mContentFrame); + mNavigationBarController.setContentFrame(contentFrame); } if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + navigationFrame); @@ -2010,21 +1837,12 @@ public class DisplayPolicy { sTmpLastParentFrame.set(windowFrames.mParentFrame); final Rect pf = windowFrames.mParentFrame; final Rect df = windowFrames.mDisplayFrame; - final Rect cf = windowFrames.mContentFrame; - final Rect vf = windowFrames.mVisibleFrame; - final Rect dcf = windowFrames.mDecorFrame; - final Rect sf = windowFrames.mStableFrame; - dcf.setEmpty(); windowFrames.setParentFrameWasClippedByDisplayCutout(false); - final int adjust = sim & SOFT_INPUT_MASK_ADJUST; - final boolean layoutInScreen = (fl & FLAG_LAYOUT_IN_SCREEN) == FLAG_LAYOUT_IN_SCREEN; final boolean layoutInsetDecor = (fl & FLAG_LAYOUT_INSET_DECOR) == FLAG_LAYOUT_INSET_DECOR; - sf.set(displayFrames.mStable); - - final InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(win); + final InsetsState state = win.getInsetsState(); computeWindowBounds(attrs, state, df); if (attached == null) { pf.set(df); @@ -2034,15 +1852,9 @@ public class DisplayPolicy { pf.inset(source.calculateInsets(pf, false /* ignoreVisibility */)); } } - vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING - ? displayFrames.mCurrent : displayFrames.mDock); } else { pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrame() : df); - vf.set(attached.getVisibleFrame()); } - cf.set(adjust != SOFT_INPUT_ADJUST_RESIZE - ? displayFrames.mDock : displayFrames.mContent); - dcf.set(displayFrames.mSystem); final int cutoutMode = attrs.layoutInDisplayCutoutMode; // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in @@ -2114,75 +1926,25 @@ public class DisplayPolicy { df.intersectUnchecked(displayCutoutSafeExceptMaybeBars); } - // Content should never appear in the cutout. - cf.intersectUnchecked(displayFrames.mDisplayCutoutSafe); - // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. // Also, we don't allow windows in multi-window mode to extend out of the screen. if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR && !win.inMultiWindowMode()) { df.left = df.top = -10000; df.right = df.bottom = 10000; - if (type != TYPE_WALLPAPER) { - cf.left = cf.top = vf.left = vf.top = -10000; - cf.right = cf.bottom = vf.right = vf.bottom = 10000; - } } if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() + ": sim=#" + Integer.toHexString(sim) + " attach=" + attached + " type=" + type + String.format(" flags=0x%08x", fl) - + " pf=" + pf.toShortString() + " df=" + df.toShortString() - + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() - + " dcf=" + dcf.toShortString() - + " sf=" + sf.toShortString()); + + " pf=" + pf.toShortString() + " df=" + df.toShortString()); if (!sTmpLastParentFrame.equals(pf)) { windowFrames.setContentChanged(true); } win.computeFrame(displayFrames); - // Dock windows carve out the bottom of the screen, so normal windows - // can't appear underneath them. - if (type == TYPE_INPUT_METHOD && win.isVisible() && !win.mGivenInsetsPending) { - offsetInputMethodWindowLw(win, displayFrames); - } - if (type == TYPE_VOICE_INTERACTION && win.isVisible() && !win.mGivenInsetsPending) { - offsetVoiceInputWindowLw(win, displayFrames); - } - } - - private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) { - final int rotation = displayFrames.mRotation; - final int navBarPosition = navigationBarPosition(displayFrames.mDisplayWidth, - displayFrames.mDisplayHeight, rotation); - - int top = Math.max(win.getDisplayFrame().top, win.getContentFrame().top); - top += win.mGivenContentInsets.top; - displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, top); - if (navBarPosition == NAV_BAR_BOTTOM) { - // Always account for the nav bar frame height on the bottom since in all navigation - // modes we make room to show the dismiss-ime button, even if the IME does not report - // insets (ie. when floating) - final int uimode = mService.mPolicy.getUiMode(); - final int navFrameHeight = getNavigationBarFrameHeight(rotation, uimode); - displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, - displayFrames.mUnrestricted.bottom - navFrameHeight); - } - displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top); - top = win.getVisibleFrame().top; - top += win.mGivenVisibleInsets.top; - displayFrames.mCurrent.bottom = Math.min(displayFrames.mCurrent.bottom, top); - if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" - + displayFrames.mDock.bottom + " mContentBottom=" - + displayFrames.mContent.bottom + " mCurBottom=" + displayFrames.mCurrent.bottom); - } - - private void offsetVoiceInputWindowLw(WindowState win, DisplayFrames displayFrames) { - int top = Math.max(win.getDisplayFrame().top, win.getContentFrame().top); - top += win.mGivenContentInsets.top; - displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top); } WindowState getTopFullscreenOpaqueWindow() { diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 73641f4d76ac..d308766b9fe5 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -492,10 +492,10 @@ class InsetsPolicy { } mAnimatingShown = show; + final InsetsState state = getInsetsForWindow(mFocusedWin); mAnimationControl = new InsetsAnimationControlImpl(controls, - mFocusedWin.getDisplayContent().getBounds(), mFocusedWin.getInsetsState(), - mListener, typesReady, this, mListener.getDurationMs(), - InsetsController.SYSTEM_BARS_INTERPOLATOR, + state.getDisplayFrame(), state, mListener, typesReady, this, + mListener.getDurationMs(), InsetsController.SYSTEM_BARS_INTERPOLATOR, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, null /* translator */); SurfaceAnimationThread.getHandler().post( () -> mListener.onReady(mAnimationControl, typesReady)); diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 2de4a7129ffe..0605ed800565 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -548,8 +548,7 @@ class InsetsSourceProvider { @Override public void startAnimation(SurfaceControl animationLeash, Transaction t, @AnimationType int type, OnAnimationFinishedCallback finishCallback) { - // TODO(b/118118435): We can remove the type check when implementing the transient bar - // animation. + // TODO(b/166736352): Check if we still need to control the IME visibility here. if (mSource.getType() == ITYPE_IME) { // TODO: use 0 alpha and remove t.hide() once b/138459974 is fixed. t.setAlpha(animationLeash, 1 /* alpha */); diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 1736ac933a80..d3ff0318de3e 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -53,6 +53,7 @@ import android.view.InputWindowHandle; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; +import android.view.WindowInsets.Type; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.SoftInputShowHideReason; @@ -534,7 +535,10 @@ public class RecentsAnimationController implements DeathRecipient { : null; final Rect contentInsets; if (mTargetActivityRecord != null && mTargetActivityRecord.findMainWindow() != null) { - contentInsets = mTargetActivityRecord.findMainWindow().getContentInsets(); + contentInsets = mTargetActivityRecord.findMainWindow() + .getInsetsStateWithVisibilityOverride() + .calculateInsets(mTargetActivityRecord.getBounds(), Type.systemBars(), + false /* ignoreVisibility */); } else { // If the window for the activity had not yet been created, use the display insets. mService.getStableInsets(mDisplayId, mTmpRect); @@ -969,8 +973,8 @@ public class RecentsAnimationController implements DeathRecipient { if (mainWindow == null) { return null; } - final Rect insets = new Rect(); - mainWindow.getContentInsets(insets); + final Rect insets = mainWindow.getInsetsStateWithVisibilityOverride().calculateInsets( + mBounds, Type.systemBars(), false /* ignoreVisibility */); InsetUtils.addInsets(insets, mainWindow.mActivityRecord.getLetterboxInsets()); final int mode = topApp.getActivityType() == mTargetActivityType ? MODE_OPENING diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 90c3f9ec21ef..6577cced1bc7 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -448,6 +448,7 @@ class Task extends WindowContainer<WindowContainer> { private final Rect mTmpBounds = new Rect(); private final Rect mTmpInsets = new Rect(); private final Rect mTmpFullBounds = new Rect(); + private static final Rect sTmpBounds = new Rect(); // Last non-fullscreen bounds the task was launched in or resized to. // The information is persisted and used to determine the appropriate stack to launch the @@ -3419,8 +3420,7 @@ class Task extends WindowContainer<WindowContainer> { * a dialog that's different in size from the activity below, in which case we should * be dimming the entire task area behind the dialog. * - * @param out Rect containing the max visible bounds. - * @return true if the task has some visible app windows; false otherwise. + * @param out the union of visible bounds. */ private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) { // skip hidden (or about to hide) apps @@ -3436,7 +3436,11 @@ class Task extends WindowContainer<WindowContainer> { out.setEmpty(); } - win.getMaxVisibleBounds(out); + final Rect visibleFrame = sTmpBounds; + visibleFrame.set(win.getFrame()); + visibleFrame.inset(win.getInsetsStateWithVisibilityOverride().calculateVisibleInsets( + visibleFrame, win.mAttrs.softInputMode)); + out.union(visibleFrame); } /** Bounds of the task to be used for dimming, as well as touch related tests. */ diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 9a818ce80872..1c6480c94131 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -85,6 +85,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { private final ActivityStackSupervisor mSupervisor; private final Rect mTmpBounds = new Rect(); + private final Rect mTmpStableBounds = new Rect(); private final int[] mTmpDirections = new int[2]; private StringBuilder mLogBuilder; @@ -425,7 +426,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // Use stable frame instead of raw frame to avoid launching freeform windows on top of // stable insets, which usually are system widgets such as sysbar & navbar. - final Rect displayStableBounds = display.mDisplayContent.mDisplayFrames.mStable; + final Rect displayStableBounds = mTmpStableBounds; + display.getStableRect(displayStableBounds); final int defaultWidth = displayStableBounds.width(); final int defaultHeight = displayStableBounds.height(); @@ -636,7 +638,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // of default size is calculated to keep the same aspect ratio as the display's. Here we use // stable bounds of displays because that indicates the area that isn't occupied by system // widgets (e.g. sysbar and navbar). - Rect displayStableBounds = display.mDisplayContent.mDisplayFrames.mStable; + final Rect displayStableBounds = mTmpStableBounds; + display.getStableRect(displayStableBounds); final int portraitHeight = Math.min(displayStableBounds.width(), displayStableBounds.height()); final int otherDimension = @@ -676,7 +679,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { private void centerBounds(@NonNull DisplayContent display, int width, int height, @NonNull Rect inOutBounds) { if (inOutBounds.isEmpty()) { - inOutBounds.set(display.mDisplayContent.mDisplayFrames.mStable); + display.getStableRect(inOutBounds); } final int left = inOutBounds.centerX() - width / 2; final int top = inOutBounds.centerY() - height / 2; @@ -685,7 +688,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { private void adjustBoundsToFitInDisplay(@NonNull DisplayContent display, @NonNull Rect inOutBounds) { - final Rect displayStableBounds = display.mDisplayContent.mDisplayFrames.mStable; + final Rect displayStableBounds = mTmpStableBounds; + display.getStableRect(displayStableBounds); if (displayStableBounds.width() < inOutBounds.width() || displayStableBounds.height() < inOutBounds.height()) { diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 3ce04aff5301..3327300793d5 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -16,9 +16,7 @@ package com.android.server.wm; -import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -39,12 +37,10 @@ import android.os.Environment; import android.os.Handler; import android.util.ArraySet; import android.util.Slog; -import android.view.InsetsSource; import android.view.InsetsState; -import android.view.InsetsState.InternalInsetsType; import android.view.SurfaceControl; import android.view.ThreadedRenderer; -import android.view.WindowInsets; +import android.view.WindowInsets.Type; import android.view.WindowManager.LayoutParams; import com.android.internal.annotations.VisibleForTesting; @@ -310,9 +306,13 @@ class TaskSnapshotController { return false; } + final Rect contentInsets = getSystemBarInsets(task.getBounds(), + mainWindow.getInsetsStateWithVisibilityOverride()); + InsetUtils.addInsets(contentInsets, activity.getLetterboxInsets()); + builder.setIsRealSnapshot(true); builder.setId(System.currentTimeMillis()); - builder.setContentInsets(getInsets(mainWindow)); + builder.setContentInsets(contentInsets); final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE; final boolean isShowWallpaper = (mainWindow.getAttrs().flags & FLAG_SHOW_WALLPAPER) != 0; @@ -420,21 +420,6 @@ class TaskSnapshotController { return mIsRunningOnWear || mIsRunningOnTv || mIsRunningOnIoT; } - private Rect getInsets(WindowState state) { - // XXX(b/72757033): These are insets relative to the window frame, but we're really - // interested in the insets relative to the task bounds. - final Rect insets = minRect(state.getContentInsets(), state.getStableInsets()); - InsetUtils.addInsets(insets, state.mActivityRecord.getLetterboxInsets()); - return insets; - } - - private Rect minRect(Rect rect1, Rect rect2) { - return new Rect(Math.min(rect1.left, rect2.left), - Math.min(rect1.top, rect2.top), - Math.min(rect1.right, rect2.right), - Math.min(rect1.bottom, rect2.bottom)); - } - /** * Retrieves all closing tasks based on the list of closing apps during an app transition. */ @@ -488,13 +473,14 @@ class TaskSnapshotController { final int color = ColorUtils.setAlphaComponent( task.getTaskDescription().getBackgroundColor(), 255); final LayoutParams attrs = mainWindow.getAttrs(); - final InsetsState insetsState = getInsetsStateWithVisibilityOverride(mainWindow); - final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState); + final Rect taskBounds = task.getBounds(); + final InsetsState insetsState = mainWindow.getInsetsStateWithVisibilityOverride(); + final Rect systemBarInsets = getSystemBarInsets(taskBounds, insetsState); final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags, attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(), mHighResTaskSnapshotScale, insetsState); - final int taskWidth = task.getBounds().width(); - final int taskHeight = task.getBounds().height(); + final int taskWidth = taskBounds.width(); + final int taskHeight = taskBounds.height(); final int width = (int) (taskWidth * mHighResTaskSnapshotScale); final int height = (int) (taskHeight * mHighResTaskSnapshotScale); @@ -510,6 +496,8 @@ class TaskSnapshotController { if (hwBitmap == null) { return null; } + final Rect contentInsets = new Rect(systemBarInsets); + InsetUtils.addInsets(contentInsets, topChild.getLetterboxInsets()); // Note, the app theme snapshot is never translucent because we enforce a non-translucent // color above @@ -518,9 +506,8 @@ class TaskSnapshotController { topChild.mActivityComponent, hwBitmap.getHardwareBuffer(), hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation, mainWindow.getWindowConfiguration().getRotation(), new Point(taskWidth, taskHeight), - getInsets(mainWindow), false /* isLowResolution */, - false /* isRealSnapshot */, task.getWindowingMode(), - getSystemUiVisibility(task), false); + contentInsets, false /* isLowResolution */, false /* isRealSnapshot */, + task.getWindowingMode(), getSystemUiVisibility(task), false); } /** @@ -611,26 +598,8 @@ class TaskSnapshotController { return 0; } - static InsetsState getInsetsStateWithVisibilityOverride(WindowState win) { - final InsetsState state = new InsetsState(win.getInsetsState()); - for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) { - final boolean requestedVisible = win.getRequestedVisibility(type); - InsetsSource source = state.peekSource(type); - if (source != null && source.isVisible() != requestedVisible) { - source = new InsetsSource(source); - source.setVisible(requestedVisible); - state.addSource(source); - } - } - return state; - } - static Rect getSystemBarInsets(Rect frame, InsetsState state) { - return state.calculateInsets(frame, null /* ignoringVisibilityState */, - false /* isScreenRound */, false /* alwaysConsumeSystemBars */, - null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacyWindowFlags */, - 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, - null /* typeSideMap */).getInsets(WindowInsets.Type.systemBars()).toRect(); + return state.calculateInsets(frame, Type.systemBars(), false /* ignoreVisibility */); } void dump(PrintWriter pw, String prefix) { diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 30f09ce9a3e6..d2cd1a1d9d61 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -43,7 +43,6 @@ import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_AT import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES; import static com.android.internal.policy.DecorView.getNavigationBarRect; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; -import static com.android.server.wm.TaskSnapshotController.getInsetsStateWithVisibilityOverride; import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -246,7 +245,7 @@ class TaskSnapshotSurface implements StartingSurface { task.getBounds(taskBounds); currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation; activityType = activity.getActivityType(); - insetsState = getInsetsStateWithVisibilityOverride(topFullscreenOpaqueWindow); + insetsState = topFullscreenOpaqueWindow.getInsetsStateWithVisibilityOverride(); } int displayId = activity.getDisplayContent().getDisplayId(); diff --git a/services/core/java/com/android/server/wm/WindowFrames.java b/services/core/java/com/android/server/wm/WindowFrames.java index 81122ac334b5..7991ec6ad59e 100644 --- a/services/core/java/com/android/server/wm/WindowFrames.java +++ b/services/core/java/com/android/server/wm/WindowFrames.java @@ -17,23 +17,16 @@ package com.android.server.wm; import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME; -import static com.android.server.wm.WindowFramesProto.CONTENT_FRAME; -import static com.android.server.wm.WindowFramesProto.CONTENT_INSETS; import static com.android.server.wm.WindowFramesProto.CUTOUT; -import static com.android.server.wm.WindowFramesProto.DECOR_FRAME; import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME; import static com.android.server.wm.WindowFramesProto.FRAME; import static com.android.server.wm.WindowFramesProto.PARENT_FRAME; -import static com.android.server.wm.WindowFramesProto.STABLE_INSETS; -import static com.android.server.wm.WindowFramesProto.VISIBLE_FRAME; -import static com.android.server.wm.WindowFramesProto.VISIBLE_INSETS; import android.annotation.NonNull; import android.graphics.Rect; import android.util.proto.ProtoOutputStream; import android.view.DisplayCutout; -import com.android.server.wm.utils.InsetUtils; import com.android.server.wm.utils.WmDisplayCutout; import java.io.PrintWriter; @@ -66,30 +59,6 @@ public class WindowFrames { public final Rect mDisplayFrame = new Rect(); /** - * Legacy stuff. Generally equal to the content frame expect when the IME for older apps - * displays hint text. - */ - public final Rect mVisibleFrame = new Rect(); - - /** - * The area not occupied by the status and navigation bars. So, if both status and navigation - * bars are visible, the decor frame is equal to the stable frame. - */ - public final Rect mDecorFrame = new Rect(); - - /** - * Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame - * minus the area occupied by the IME if the IME is present. - */ - public final Rect mContentFrame = new Rect(); - - /** - * The display frame minus the stable insets. This value is always constant regardless of if - * the status bar or navigation bar is visible. - */ - public final Rect mStableFrame = new Rect(); - - /** * Similar to {@link #mDisplayFrame} * * TODO: Why is this different than mDisplayFrame @@ -139,52 +108,21 @@ public class WindowFrames { private boolean mDisplayCutoutChanged; - /** - * Insets that determine the area covered by the stable system windows. These are in the - * application's coordinate space (without compatibility scale applied). - */ - final Rect mStableInsets = new Rect(); - final Rect mLastStableInsets = new Rect(); - private boolean mStableInsetsChanged; - - /** - * Insets that determine the actually visible area. These are in the application's - * coordinate space (without compatibility scale applied). - */ - final Rect mVisibleInsets = new Rect(); - final Rect mLastVisibleInsets = new Rect(); - private boolean mVisibleInsetsChanged; - - /** - * Insets that are covered by system windows (such as the status bar) and - * transient docking windows (such as the IME). These are in the application's - * coordinate space (without compatibility scale applied). - */ - final Rect mContentInsets = new Rect(); - final Rect mLastContentInsets = new Rect(); - private boolean mContentInsetsChanged; - - private final Rect mTmpRect = new Rect(); + boolean mLastForceReportingResized = false; + boolean mForceReportingResized = false; private boolean mContentChanged; public WindowFrames() { } - public WindowFrames(Rect parentFrame, Rect displayFrame, Rect contentFrame, - Rect visibleFrame, Rect decorFrame, Rect stableFrame) { - setFrames(parentFrame, displayFrame, contentFrame, visibleFrame, decorFrame, - stableFrame); + public WindowFrames(Rect parentFrame, Rect displayFrame) { + setFrames(parentFrame, displayFrame); } - public void setFrames(Rect parentFrame, Rect displayFrame, - Rect contentFrame, Rect visibleFrame, Rect decorFrame, Rect stableFrame) { + public void setFrames(Rect parentFrame, Rect displayFrame) { mParentFrame.set(parentFrame); mDisplayFrame.set(displayFrame); - mContentFrame.set(contentFrame); - mVisibleFrame.set(visibleFrame); - mDecorFrame.set(decorFrame); - mStableFrame.set(stableFrame); } public void setParentFrameWasClippedByDisplayCutout( @@ -207,49 +145,8 @@ public class WindowFrames { return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height()); } - /** - * Calculate the insets for a window. - * - * @param windowsAreFloating Whether the window is in a floating task such as pinned or - * freeform - * @param inFullscreenContainer Whether the window is in a container that takes up the screen's - * entire space - * @param windowBounds The bounds for the window - */ - void calculateInsets(boolean windowsAreFloating, boolean inFullscreenContainer, - Rect windowBounds) { - // Override right and/or bottom insets in case if the frame doesn't fit the screen in - // non-fullscreen mode. - boolean overrideRightInset = !windowsAreFloating && !inFullscreenContainer - && mFrame.right > windowBounds.right; - boolean overrideBottomInset = !windowsAreFloating && !inFullscreenContainer - && mFrame.bottom > windowBounds.bottom; - - mTmpRect.set(mFrame.left, mFrame.top, - overrideRightInset ? windowBounds.right : mFrame.right, - overrideBottomInset ? windowBounds.bottom : mFrame.bottom); - - InsetUtils.insetsBetweenFrames(mTmpRect, mContentFrame, mContentInsets); - InsetUtils.insetsBetweenFrames(mTmpRect, mVisibleFrame, mVisibleInsets); - InsetUtils.insetsBetweenFrames(mTmpRect, mStableFrame, mStableInsets); - } - - /** - * Scales all the insets by a specific amount. - * - * @param scale The amount to scale the insets by. - */ - void scaleInsets(float scale) { - mContentInsets.scale(scale); - mVisibleInsets.scale(scale); - mStableInsets.scale(scale); - } - void offsetFrames(int layoutXDiff, int layoutYDiff) { mFrame.offset(layoutXDiff, layoutYDiff); - mContentFrame.offset(layoutXDiff, layoutYDiff); - mVisibleFrame.offset(layoutXDiff, layoutYDiff); - mStableFrame.offset(layoutXDiff, layoutYDiff); } /** @@ -258,44 +155,35 @@ public class WindowFrames { * @return true if info about size has changed since last reported. */ boolean setReportResizeHints() { - mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets); - mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets); - mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets); + mLastForceReportingResized |= mForceReportingResized; mFrameSizeChanged |= didFrameSizeChange(); mDisplayCutoutChanged |= !mLastDisplayCutout.equals(mDisplayCutout); - return mContentInsetsChanged || mVisibleInsetsChanged - || mStableInsetsChanged || mFrameSizeChanged - || mDisplayCutoutChanged; + return mLastForceReportingResized || mFrameSizeChanged || mDisplayCutoutChanged; } /** - * Resets the insets changed flags so they're all set to false again. This should be called - * after the insets are reported to client. + * Resets the size changed flags so they're all set to false again. This should be called + * after the frames are reported to client. */ - void resetInsetsChanged() { - mContentInsetsChanged = false; - mVisibleInsetsChanged = false; - mStableInsetsChanged = false; + void clearReportResizeHints() { + mLastForceReportingResized = false; mFrameSizeChanged = false; mDisplayCutoutChanged = false; } /** - * Copy over inset values as the last insets that were sent to the client. + * Clears factors that would cause report-resize. */ - void updateLastInsetValues() { - mLastContentInsets.set(mContentInsets); - mLastVisibleInsets.set(mVisibleInsets); - mLastStableInsets.set(mStableInsets); + void onResizeHandled() { + mForceReportingResized = false; mLastDisplayCutout = mDisplayCutout; } /** - * Sets the last content insets as (-1, -1, -1, -1) to force the next layout pass to update - * the client. + * Forces the next layout pass to update the client. */ - void resetLastContentInsets() { - mLastContentInsets.set(-1, -1, -1, -1); + void forceReportingResized() { + mForceReportingResized = true; } /** @@ -316,16 +204,10 @@ public class WindowFrames { public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); mParentFrame.dumpDebug(proto, PARENT_FRAME); - mContentFrame.dumpDebug(proto, CONTENT_FRAME); mDisplayFrame.dumpDebug(proto, DISPLAY_FRAME); - mVisibleFrame.dumpDebug(proto, VISIBLE_FRAME); - mDecorFrame.dumpDebug(proto, DECOR_FRAME); mContainingFrame.dumpDebug(proto, CONTAINING_FRAME); mFrame.dumpDebug(proto, FRAME); mDisplayCutout.getDisplayCutout().dumpDebug(proto, CUTOUT); - mContentInsets.dumpDebug(proto, CONTENT_INSETS); - mVisibleInsets.dumpDebug(proto, VISIBLE_INSETS); - mStableInsets.dumpDebug(proto, STABLE_INSETS); proto.end(token); } @@ -333,36 +215,16 @@ public class WindowFrames { public void dump(PrintWriter pw, String prefix) { pw.println(prefix + "Frames: containing=" + mContainingFrame.toShortString(sTmpSB) - + " parent=" + mParentFrame.toShortString(sTmpSB)); - pw.println(prefix + " display=" + mDisplayFrame.toShortString(sTmpSB)); - pw.println(prefix + " content=" + mContentFrame.toShortString(sTmpSB) - + " visible=" + mVisibleFrame.toShortString(sTmpSB)); - pw.println(prefix + " decor=" + mDecorFrame.toShortString(sTmpSB)); + + " parent=" + mParentFrame.toShortString(sTmpSB) + + " display=" + mDisplayFrame.toShortString(sTmpSB)); pw.println(prefix + "mFrame=" + mFrame.toShortString(sTmpSB) + " last=" + mLastFrame.toShortString(sTmpSB)); pw.println(prefix + " cutout=" + mDisplayCutout.getDisplayCutout() + " last=" + mLastDisplayCutout.getDisplayCutout()); - pw.print(prefix + "Cur insets: content=" + mContentInsets.toShortString(sTmpSB) - + " visible=" + mVisibleInsets.toShortString(sTmpSB) - + " stable=" + mStableInsets.toShortString(sTmpSB)); - pw.println(prefix + "Lst insets: content=" + mLastContentInsets.toShortString(sTmpSB) - + " visible=" + mLastVisibleInsets.toShortString(sTmpSB) - + " stable=" + mLastStableInsets.toShortString(sTmpSB)); - } - - String getInsetsInfo() { - return "ci=" + mContentInsets.toShortString() - + " vi=" + mVisibleInsets.toShortString() - + " si=" + mStableInsets.toShortString(); } String getInsetsChangedInfo() { - return "contentInsetsChanged=" + mContentInsetsChanged - + " " + mContentInsets.toShortString() - + " visibleInsetsChanged=" + mVisibleInsetsChanged - + " " + mVisibleInsets.toShortString() - + " stableInsetsChanged=" + mStableInsetsChanged - + " " + mStableInsets.toShortString() + return "forceReportingResized=" + mLastForceReportingResized + " displayCutoutChanged=" + mDisplayCutoutChanged; } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 782d6e39bf53..fbcbe00cdf5d 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1916,7 +1916,9 @@ public class WindowManagerService extends IWindowManager.Stub } // We use the visible frame, because we want the animation to morph the window from what // was visible to the user to the final destination of the new window. - Rect frame = replacedWindow.getVisibleFrame(); + final Rect frame = new Rect(replacedWindow.getFrame()); + frame.inset(replacedWindow.getInsetsStateWithVisibilityOverride().calculateVisibleInsets( + frame, replacedWindow.mAttrs.softInputMode)); // We treat this as if this activity was opening, so we can trigger the app transition // animation and piggy-back on existing transition animation infrastructure. final DisplayContent dc = activity.getDisplayContent(); @@ -2460,12 +2462,11 @@ public class WindowManagerService extends IWindowManager.Stub win.setLastReportedMergedConfiguration(mergedConfiguration); - // Update the last inset values here because the values are sent back to the client. - // The last inset values represent the last client state - win.updateLastInsetValues(); + // Set resize-handled here because the values are sent back to the client. + win.onResizeHandled(); win.fillClientWindowFrames(outFrames); - outInsetsState.set(win.getInsetsState(), win.isClientLocal()); + outInsetsState.set(win.getCompatInsetsState(), win.isClientLocal()); if (DEBUG) { Slog.v(TAG_WM, "Relayout given client " + client.asBinder() + ", requestedWidth=" + requestedWidth @@ -7564,7 +7565,7 @@ public class WindowManagerService extends IWindowManager.Stub public int getInputMethodWindowVisibleHeight(int displayId) { synchronized (mGlobalLock) { final DisplayContent dc = mRoot.getDisplayContent(displayId); - return dc.mDisplayFrames.getInputMethodWindowVisibleHeight(); + return dc.getInputMethodWindowVisibleHeight(); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 04d777299ecc..d972a519cf17 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -30,13 +30,15 @@ import static android.os.IInputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.PowerManager.DRAW_WAKE_LOCK; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.InsetsState.ITYPE_IME; +import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.SurfaceControl.Transaction; -import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; -import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE; +import static android.view.WindowInsets.Type.displayCutout; +import static android.view.WindowInsets.Type.ime; +import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; @@ -798,11 +800,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } boolean isImplicitlyExcludingAllSystemGestures() { - final int immersiveStickyFlags = - SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - final boolean immersiveSticky = - (mSystemUiVisibility & immersiveStickyFlags) == immersiveStickyFlags; - return immersiveSticky && mWmService.mConstants.mSystemGestureExcludedByPreQStickyImmersive + final boolean stickyHideNav = + mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + && !getRequestedVisibility(ITYPE_NAVIGATION_BAR); + return stickyHideNav && mWmService.mConstants.mSystemGestureExcludedByPreQStickyImmersive && mActivityRecord != null && mActivityRecord.mTargetSdk < Build.VERSION_CODES.Q; } @@ -1121,12 +1122,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (isImeTarget) { if (inFreeformWindowingMode()) { // Push the freeform window up to make room for the IME. However, don't push - // it up past the top of the screen. - final int bottomOverlap = windowFrames.mContainingFrame.bottom - - windowFrames.mVisibleFrame.bottom; + // it up past the bottom of the top bar. + final InsetsState state = dc.getInsetsStateController().getRawInsetsState(); + final Rect visibleFrame = mTmpRect; + visibleFrame.set(state.getDisplayFrame()); + visibleFrame.inset(state.calculateInsets(visibleFrame, + systemBars() | ime() | displayCutout(), false /* ignoreVisibility */)); + final int bottomOverlap = + windowFrames.mContainingFrame.bottom - visibleFrame.bottom; if (bottomOverlap > 0) { final int distanceToTop = Math.max(windowFrames.mContainingFrame.top - - windowFrames.mContentFrame.top, 0); + - visibleFrame.top, 0); int offs = Math.min(bottomOverlap, distanceToTop); windowFrames.mContainingFrame.offset(0, -offs); mInsetFrame.offset(0, -offs); @@ -1145,7 +1151,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // if it wasn't set already. No need to intersect it with the (visible) // "content frame" since it is allowed to be outside the visible desktop. if (windowFrames.mContainingFrame.isEmpty()) { - windowFrames.mContainingFrame.set(windowFrames.mContentFrame); + windowFrames.mContainingFrame.set(windowFrames.mDisplayFrame); } } @@ -1180,52 +1186,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP applyGravityAndUpdateFrame(windowFrames, layoutContainingFrame, layoutDisplayFrame); - // Make sure the content and visible frames are inside of the - // final window frame. - if (windowsAreFloating && !windowFrames.mFrame.isEmpty()) { - final int visBottom = windowFrames.mVisibleFrame.bottom; - final int contentBottom = windowFrames.mContentFrame.bottom; - windowFrames.mContentFrame.set(windowFrames.mFrame); - windowFrames.mVisibleFrame.set(windowFrames.mContentFrame); - windowFrames.mStableFrame.set(windowFrames.mContentFrame); - if (isImeTarget && inFreeformWindowingMode()) { - // After displacing a freeform window to make room for the ime, any part of - // the window still covered by IME should be inset. - if (contentBottom + layoutYDiff < windowFrames.mContentFrame.bottom) { - windowFrames.mContentFrame.bottom = contentBottom + layoutYDiff; - } - if (visBottom + layoutYDiff < windowFrames.mVisibleFrame.bottom) { - windowFrames.mVisibleFrame.bottom = visBottom + layoutYDiff; - } - } - } else if (mAttrs.type == TYPE_DOCK_DIVIDER) { - windowFrames.mContentFrame.set(windowFrames.mFrame); + if (mAttrs.type == TYPE_DOCK_DIVIDER) { if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) { mMovedByResize = true; } - } else { - windowFrames.mContentFrame.set( - Math.max(windowFrames.mContentFrame.left, windowFrames.mFrame.left), - Math.max(windowFrames.mContentFrame.top, windowFrames.mFrame.top), - Math.min(windowFrames.mContentFrame.right, windowFrames.mFrame.right), - Math.min(windowFrames.mContentFrame.bottom, windowFrames.mFrame.bottom)); - - windowFrames.mVisibleFrame.set( - Math.max(windowFrames.mVisibleFrame.left, windowFrames.mFrame.left), - Math.max(windowFrames.mVisibleFrame.top, windowFrames.mFrame.top), - Math.min(windowFrames.mVisibleFrame.right, windowFrames.mFrame.right), - Math.min(windowFrames.mVisibleFrame.bottom, windowFrames.mFrame.bottom)); - - windowFrames.mStableFrame.set( - Math.max(windowFrames.mStableFrame.left, windowFrames.mFrame.left), - Math.max(windowFrames.mStableFrame.top, windowFrames.mFrame.top), - Math.min(windowFrames.mStableFrame.right, windowFrames.mFrame.right), - Math.min(windowFrames.mStableFrame.bottom, windowFrames.mFrame.bottom)); } - windowFrames.calculateInsets(windowsAreFloating, isFullscreenAndFillsDisplay, - getDisplayFrames(dc.mDisplayFrames).mUnrestricted); - windowFrames.setDisplayCutout( windowFrames.mDisplayCutout.calculateRelativeTo(windowFrames.mFrame)); @@ -1234,11 +1200,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP windowFrames.mCompatFrame.set(windowFrames.mFrame); if (inSizeCompatMode()) { - // If there is a size compatibility scale being applied to the - // window, we need to apply this to its insets so that they are - // reported to the app in its coordinate space. - windowFrames.scaleInsets(mInvGlobalScale); - // Also the scaled frame that we report to the app needs to be // adjusted to be in its coordinate space. windowFrames.mCompatFrame.scale(mInvGlobalScale); @@ -1270,7 +1231,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP + mRequestedWidth + ", mRequestedheight=" + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph + "): frame=" + windowFrames.mFrame.toShortString() - + " " + windowFrames.getInsetsInfo() + " " + mAttrs.getTitle()); } } @@ -1303,33 +1263,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return mWindowFrames.mDisplayFrame; } - /** - * Retrieves the frame of the content area that this window was last laid out in. This is the - * area in which the content of the window should be placed. It will be smaller than the display - * frame to account for screen decorations such as a status bar or soft keyboard. - */ - Rect getContentFrame() { - return mWindowFrames.mContentFrame; - } - - /** - * Retrieves the frame of the visible area that this window was last laid out in. This is the - * area of the screen in which the window will actually be fully visible. It will be smaller - * than the content frame to account for transient UI elements blocking it such as an input - * method's candidates UI. - */ - Rect getVisibleFrame() { - return mWindowFrames.mVisibleFrame; - } - - Rect getStableFrame() { - return mWindowFrames.mStableFrame; - } - - Rect getDecorFrame() { - return mWindowFrames.mDecorFrame; - } - Rect getParentFrame() { return mWindowFrames.mParentFrame; } @@ -1342,10 +1275,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return mWindowFrames.mDisplayCutout; } - void getCompatFrame(Rect outFrame) { - outFrame.set(mWindowFrames.mCompatFrame); - } - void getCompatFrameSize(Rect outFrame) { outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height()); } @@ -1433,7 +1362,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return; } - updateLastInsetValues(); + onResizeHandled(); mWmService.makeWindowFreezingScreenIfNeededLocked(this); // If the orientation is changing, or we're starting or ending a drag resizing action, @@ -1534,11 +1463,19 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } /** - * Returns the insets state for the client. Its sources may be the copies with visibility + * Returns the insets state for the window. Its sources may be the copies with visibility * modification according to the state of transient bars. */ InsetsState getInsetsState() { - InsetsState state = getDisplayContent().getInsetsPolicy().getInsetsForWindow(this); + return getDisplayContent().getInsetsPolicy().getInsetsForWindow(this); + } + + /** + * Returns the insets state for the client and scales the frames if the client is in the size + * compatible mode. + */ + InsetsState getCompatInsetsState() { + InsetsState state = getInsetsState(); if (inSizeCompatMode()) { state = new InsetsState(state, true); state.scale(mInvGlobalScale); @@ -1546,6 +1483,23 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return state; } + /** + * Returns the insets state for the window and applies the requested visibility. + */ + InsetsState getInsetsStateWithVisibilityOverride() { + final InsetsState state = new InsetsState(getInsetsState()); + for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) { + final boolean requestedVisible = getRequestedVisibility(type); + InsetsSource source = state.peekSource(type); + if (source != null && source.isVisible() != requestedVisible) { + source = new InsetsSource(source); + source.setVisible(requestedVisible); + state.addSource(source); + } + } + return state; + } + int getDisplayId() { final DisplayContent displayContent = getDisplayContent(); if (displayContent == null) { @@ -1625,18 +1579,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - bounds.set(mWindowFrames.mVisibleFrame); + bounds.set(mWindowFrames.mFrame); + bounds.inset(getInsetsStateWithVisibilityOverride().calculateVisibleInsets( + bounds, mAttrs.softInputMode)); if (intersectWithStackBounds) { bounds.intersect(mTmpRect); } - - if (bounds.isEmpty()) { - bounds.set(mWindowFrames.mFrame); - if (intersectWithStackBounds) { - bounds.intersect(mTmpRect); - } - return; - } } public long getInputDispatchingTimeoutMillis() { @@ -1958,7 +1906,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWinAnimator.mDrawState = DRAW_PENDING; // Force add to {@link WindowManagerService#mResizingWindows}. - resetLastContentInsets(); + forceReportingResized(); outWaitingForDrawn.add(this); } @@ -3423,8 +3371,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // bottom right. if (win.getFrame().left <= win.getDisplayFrame().left && win.getFrame().top <= win.getDisplayFrame().top - && win.getFrame().right >= win.getStableFrame().right - && win.getFrame().bottom >= win.getStableFrame().bottom) { + && win.getFrame().right >= win.getDisplayFrame().right + && win.getFrame().bottom >= win.getDisplayFrame().bottom) { // Is a fullscreen window, like the clock alarm. Show to everyone. return true; } @@ -3623,7 +3571,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // that may cause WINDOW_FREEZE_TIMEOUT because resizing the client keeps failing. mReportOrientationChanged = false; mDragResizingChangeReported = true; - mWindowFrames.resetInsetsChanged(); + mWindowFrames.clearReportResizeHints(); final MergedConfiguration mergedConfiguration = mLastReportedConfiguration; final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING || useBLASTSync() || !mRedrawForSyncReported; @@ -3692,7 +3640,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP void notifyInsetsChanged() { ProtoLog.d(WM_DEBUG_IME, "notifyInsetsChanged for %s ", this); try { - mClient.insetsChanged(getInsetsState()); + mClient.insetsChanged(getCompatInsetsState()); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver inset state change w=" + this, e); } @@ -3707,7 +3655,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final InsetsStateController stateController = getDisplayContent().getInsetsStateController(); try { - mClient.insetsControlChanged(getInsetsState(), + mClient.insetsControlChanged(getCompatInsetsState(), stateController.getControlsForDispatch(this)); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver inset state change to w=" + this, e); @@ -4917,24 +4865,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - private boolean skipDecorCrop() { - // The decor frame is used to specify the region not covered by the system - // decorations (nav bar, status bar). In case this is empty, for example with - // FLAG_TRANSLUCENT_NAVIGATION, we don't need to do any cropping. - if (mWindowFrames.mDecorFrame.isEmpty()) { - return true; - } - - // But if we have a frame, and are an application window, then we must be cropped. - if (mActivityRecord != null) { - return false; - } - - // For non application windows, we may be allowed to extend over the decor bars - // depending on our type and permissions assosciated with our token. - return mToken.canLayerAboveSystemBars(); - } - /** * Expand the given rectangle by this windows surface insets. This * takes you from the 'window size' to the 'surface size'. @@ -5062,10 +4992,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } /** - * Updates the last inset values to the current ones. + * Clears factors that would cause report-resize. */ - void updateLastInsetValues() { - mWindowFrames.updateLastInsetValues(); + void onResizeHandled() { + mWindowFrames.onResizeHandled(); } @Override @@ -5550,48 +5480,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mFrameNumber = frameNumber; } - public void getMaxVisibleBounds(Rect out) { - if (out.isEmpty()) { - out.set(mWindowFrames.mVisibleFrame); - return; - } - - if (mWindowFrames.mVisibleFrame.left < out.left) { - out.left = mWindowFrames.mVisibleFrame.left; - } - if (mWindowFrames.mVisibleFrame.top < out.top) { - out.top = mWindowFrames.mVisibleFrame.top; - } - if (mWindowFrames.mVisibleFrame.right > out.right) { - out.right = mWindowFrames.mVisibleFrame.right; - } - if (mWindowFrames.mVisibleFrame.bottom > out.bottom) { - out.bottom = mWindowFrames.mVisibleFrame.bottom; - } - } - - void getContentInsets(Rect outContentInsets) { - outContentInsets.set(mWindowFrames.mContentInsets); - } - - Rect getContentInsets() { - return mWindowFrames.mContentInsets; - } - - void getStableInsets(Rect outStableInsets) { - outStableInsets.set(mWindowFrames.mStableInsets); - } - - Rect getStableInsets() { - return mWindowFrames.mStableInsets; - } - - void resetLastContentInsets() { - mWindowFrames.resetLastContentInsets(); - } - - Rect getVisibleInsets() { - return mWindowFrames.mVisibleInsets; + void forceReportingResized() { + mWindowFrames.forceReportingResized(); } /** Returns the {@link WindowFrames} associated with this {@link WindowState}. */ @@ -5719,10 +5609,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP outFrame.set(getContainingFrame()); } outSurfaceInsets.set(getAttrs().surfaceInsets); - // TODO(b/72757033): These are insets relative to the window frame, but we're really - // interested in the insets relative to the frame we chose in the if-blocks above. - getContentInsets(outInsets); - getStableInsets(outStableInsets); + final InsetsState state = getInsetsStateWithVisibilityOverride(); + outInsets.set(state.calculateInsets(outFrame, systemBars(), + false /* ignoreVisibility */)); + outStableInsets.set(state.calculateInsets(outFrame, systemBars(), + true /* ignoreVisibility */)); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index dc33b75ec57a..ec30dc5def86 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -30,11 +30,11 @@ import static android.view.Display.FLAG_PRIVATE; import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT; import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; import static android.view.DisplayCutout.fromBoundingRect; +import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; +import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_90; -import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN; -import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; -import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; +import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; @@ -101,6 +101,7 @@ import android.view.IDisplayWindowRotationCallback; import android.view.IDisplayWindowRotationController; import android.view.ISystemGestureExclusionListener; import android.view.IWindowManager; +import android.view.InsetsState; import android.view.MotionEvent; import android.view.Surface; import android.view.SurfaceControl.Transaction; @@ -1092,9 +1093,11 @@ public class DisplayContentTests extends WindowTestsBase { win.getAttrs().flags |= FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; win.getAttrs().layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; win.getAttrs().privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION; - win.getAttrs().subtreeSystemUiVisibility = win.mSystemUiVisibility = - SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION - | SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + win.getAttrs().insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; + final InsetsState requestedState = new InsetsState(); + requestedState.getSource(ITYPE_NAVIGATION_BAR).setVisible(false); + requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false); + win.updateRequestedVisibility(requestedState); win.mActivityRecord.mTargetSdk = P; performLayout(dc); 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 3598cd8d841d..378a0a82c12f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -16,10 +16,6 @@ package com.android.server.wm; -import static android.view.Gravity.BOTTOM; -import static android.view.Gravity.LEFT; -import static android.view.Gravity.RIGHT; -import static android.view.Gravity.TOP; import static android.view.InsetsState.ITYPE_CLIMATE_BAR; import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; @@ -32,12 +28,10 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; @@ -58,7 +52,6 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.testng.Assert.expectThrows; @@ -106,7 +99,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { private int mRotation = ROTATION_0; private boolean mHasDisplayCutout; private boolean mIsLongEdgeDisplayCutout; - private static final int DECOR_WINDOW_INSET = 50; private final Rect mDisplayBounds = new Rect(); @@ -282,12 +274,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, 0); assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); } @Test @@ -298,12 +286,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getDisplayFrame(), 0, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); } @Test @@ -314,12 +298,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); } @Test @@ -330,18 +310,13 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, 0); assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); } @Test public void layoutWindowLw_fitInsetsIgnoringVisibility() { - final InsetsState state = - mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow); + final InsetsState state = mWindow.getInsetsState(); state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false); mWindow.mAttrs.setFitInsetsIgnoringVisibility(true); @@ -350,18 +325,13 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); } @Test public void layoutWindowLw_fitInsetsNotIgnoringVisibility() { - final InsetsState state = - mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow); + final InsetsState state = mWindow.getInsetsState(); state.getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); state.getSource(InsetsState.ITYPE_NAVIGATION_BAR).setVisible(false); mWindow.mAttrs.setFitInsetsIgnoringVisibility(false); @@ -370,12 +340,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getDisplayFrame(), 0, 0); assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); } @Test @@ -407,12 +373,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); assertInsetByTopBottom(mWindow.getDisplayFrame(), DISPLAY_CUTOUT_HEIGHT, 0); assertInsetByTopBottom(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); } @Test @@ -428,9 +390,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); assertInsetByTopBottom(mWindow.getDisplayFrame(), 0, 0); } @@ -448,9 +407,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, 0); } @@ -468,9 +424,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getContentFrame(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), 0, 0, 0, 0); } @@ -488,9 +441,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getContentFrame(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), 0, 0, 0, 0); } @@ -509,9 +459,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); assertInsetByTopBottom(mWindow.getDisplayFrame(), 0, 0); } @@ -522,8 +469,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow) - .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); + mWindow.getInsetsState().getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); final InsetsState requestedState = new InsetsState(); requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false); mWindow.updateRequestedVisibility(requestedState); @@ -533,9 +479,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, 0); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); assertInsetByTopBottom(mWindow.getDisplayFrame(), STATUS_BAR_HEIGHT, 0); } @@ -546,8 +489,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mWindow.mAttrs.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; mWindow.mAttrs.setFitInsetsTypes(0 /* types */); - mDisplayContent.getInsetsPolicy().getInsetsForWindow(mWindow) - .getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); + mWindow.getInsetsState().getSource(InsetsState.ITYPE_STATUS_BAR).setVisible(false); final InsetsState requestedState = new InsetsState(); requestedState.getSource(ITYPE_STATUS_BAR).setVisible(false); mWindow.updateRequestedVisibility(requestedState); @@ -558,9 +500,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0); assertInsetByTopBottom(mWindow.getDisplayFrame(), 0, 0); } @@ -578,10 +517,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getContentFrame(), - DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); } @@ -599,10 +534,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); - assertInsetBy(mWindow.getStableFrame(), NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, 0, 0); - assertInsetBy(mWindow.getContentFrame(), - NAV_BAR_HEIGHT, STATUS_BAR_HEIGHT, DISPLAY_CUTOUT_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), 0, 0, DISPLAY_CUTOUT_HEIGHT, 0); } @@ -622,10 +553,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getContentFrame(), - DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); } @Test @@ -663,10 +590,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getContentFrame(), - DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT, 0); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); } @Test @@ -682,10 +605,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getContentFrame(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, - NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); } @@ -703,11 +622,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, 0, - NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getContentFrame(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, - NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); } @@ -725,10 +639,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getContentFrame(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, - NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), DISPLAY_CUTOUT_HEIGHT, 0, 0, 0); } @@ -746,10 +656,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); - assertInsetBy(mWindow.getStableFrame(), 0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getContentFrame(), DISPLAY_CUTOUT_HEIGHT, STATUS_BAR_HEIGHT, 0, - NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), 0, 0, 0, 0); } @@ -767,10 +673,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); assertInsetBy(mWindow.getParentFrame(), 0, 0, 0, 0); - assertInsetByTopBottom(mWindow.getStableFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetByTopBottom(mWindow.getVisibleFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - assertInsetBy(mWindow.getDecorFrame(), 0, 0, 0, 0); assertInsetBy(mWindow.getDisplayFrame(), 0, 0, 0, 0); } @@ -832,10 +734,16 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { // Initialize DisplayFrames mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); + final InsetsState state = + mDisplayContent.getInsetsStateController().getRawInsetsState(); + final Rect contentFrame = new Rect(state.getDisplayFrame()); + contentFrame.inset(state.calculateInsets(contentFrame, Type.systemBars(), + false /* ignoreVisibility */)); + // Task is in the nav bar area (usually does not happen, but this is similar enough to // the possible overlap with the IME) - final Rect taskBounds = new Rect(100, mFrames.mContent.bottom + 1, - 200, mFrames.mContent.bottom + 10); + final Rect taskBounds = new Rect(100, contentFrame.bottom + 1, + 200, contentFrame.bottom + 10); final Task task = mWindow.getTask(); // Make the task floating. @@ -915,59 +823,6 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { assertEquals(DISPLAY_HEIGHT, rotatedFrame.width()); } - @Test - public void testScreenDecorWindows() { - final WindowState decorWindow = spy( - createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow")); - mWindow.mAttrs.flags = FLAG_NOT_FOCUSABLE | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR - | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; - decorWindow.mAttrs.privateFlags |= PRIVATE_FLAG_IS_SCREEN_DECOR; - addWindow(decorWindow); - addWindow(mWindow); - doReturn(new Rect(0, 0, mFrames.mDisplayWidth, mFrames.mDisplayHeight)) - .when(decorWindow).getBounds(); - - // Decor on top - updateDecorWindow(decorWindow, MATCH_PARENT, DECOR_WINDOW_INSET, TOP); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getContentFrame(), DECOR_WINDOW_INSET, NAV_BAR_HEIGHT); - - // Decor on bottom - updateDecorWindow(decorWindow, MATCH_PARENT, DECOR_WINDOW_INSET, BOTTOM); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, - DECOR_WINDOW_INSET); - - // Decor on the left - updateDecorWindow(decorWindow, DECOR_WINDOW_INSET, MATCH_PARENT, LEFT); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetBy(mWindow.getContentFrame(), DECOR_WINDOW_INSET, STATUS_BAR_HEIGHT, 0, - NAV_BAR_HEIGHT); - - // Decor on the right - updateDecorWindow(decorWindow, DECOR_WINDOW_INSET, MATCH_PARENT, RIGHT); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetBy(mWindow.getContentFrame(), 0, STATUS_BAR_HEIGHT, DECOR_WINDOW_INSET, - NAV_BAR_HEIGHT); - - // Decor not allowed as inset - updateDecorWindow(decorWindow, DECOR_WINDOW_INSET, DECOR_WINDOW_INSET, TOP); - mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); - mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames); - assertInsetByTopBottom(mWindow.getContentFrame(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT); - } - - private void updateDecorWindow(WindowState decorWindow, int width, int height, int gravity) { - decorWindow.mAttrs.width = width; - decorWindow.mAttrs.height = height; - decorWindow.mAttrs.gravity = gravity; - decorWindow.setRequestedSize(width, height); - } - /** * Asserts that {@code actual} is inset by the given amounts from the full display rect. * diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index bbe811d15258..e0fd3796f2aa 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -356,7 +356,7 @@ public class InsetsPolicyTest extends WindowTestsBase { assertNull(controls[i].getLeash()); } - final InsetsState state = policy.getInsetsForWindow(mAppWindow); + final InsetsState state = mAppWindow.getInsetsState(); state.setSourceVisible(ITYPE_STATUS_BAR, true); state.setSourceVisible(ITYPE_NAVIGATION_BAR, true); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index a1097d26fbbb..98520bb7a20b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -28,6 +28,10 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.util.DisplayMetrics.DENSITY_DEFAULT; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.InsetsState.ITYPE_CLIMATE_BAR; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; +import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; +import static android.view.InsetsState.ITYPE_STATUS_BAR; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -36,6 +40,8 @@ import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier. import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import android.app.ActivityOptions; import android.content.pm.ActivityInfo; @@ -45,6 +51,7 @@ import android.graphics.Rect; import android.os.Build; import android.platform.test.annotations.Presubmit; import android.view.Gravity; +import android.view.InsetsState; import androidx.test.filters.SmallTest; @@ -1114,8 +1121,9 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { // This test case requires a relatively big app bounds to ensure the default size calculated // by letterbox won't be too small to hold the minimum width/height. - freeformDisplay.mDisplayContent.mDisplayFrames.mStable.set(/* left */ 10, /* top */ 10, - /* right */ 1910, /* top */ 1070); + configInsetsState( + freeformDisplay.getInsetsStateController().getRawInsetsState(), + DISPLAY_BOUNDS, new Rect(10, 10, 1910, 1070)); final ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(freeformDisplay.mDisplayId); @@ -1339,15 +1347,45 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { display.setBounds(DISPLAY_BOUNDS); display.getConfiguration().densityDpi = DENSITY_DEFAULT; display.getConfiguration().orientation = ORIENTATION_LANDSCAPE; - display.mDisplayContent.mDisplayFrames.mStable.set(DISPLAY_STABLE_BOUNDS); - spyOn(display.mDisplayContent.mDisplayFrames); + configInsetsState(display.getInsetsStateController().getRawInsetsState(), + DISPLAY_BOUNDS, DISPLAY_STABLE_BOUNDS); // We didn't set up the overall environment for this test, so we need to mute the side // effect of layout passes that loosen the stable frame. - doNothing().when(display.mDisplayContent.mDisplayFrames).onBeginLayout(); + final DisplayPolicy policy = display.getDisplayPolicy(); + spyOn(policy); + doNothing().when(policy).beginLayoutLw(any(), anyInt()); return display; } + /** + * Creates insets sources so that we can get the expected stable frame. + */ + private static void configInsetsState(InsetsState state, Rect displayFrame, Rect stableFrame) { + final int dl = displayFrame.left; + final int dt = displayFrame.top; + final int dr = displayFrame.right; + final int db = displayFrame.bottom; + final int sl = stableFrame.left; + final int st = stableFrame.top; + final int sr = stableFrame.right; + final int sb = stableFrame.bottom; + + state.setDisplayFrame(displayFrame); + if (sl > dl) { + state.getSource(ITYPE_CLIMATE_BAR).setFrame(dl, dt, sl, db); + } + if (st > dt) { + state.getSource(ITYPE_STATUS_BAR).setFrame(dl, dt, dr, st); + } + if (sr < dr) { + state.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(sr, dt, dr, db); + } + if (sb < db) { + state.getSource(ITYPE_NAVIGATION_BAR).setFrame(dl, sb, dr, db); + } + } + private ActivityRecord createSourceActivity(TestDisplayContent display) { final Task stack = display.getDefaultTaskDisplayArea() .createStack(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java index 0cf63f4ff21d..d2be50d02ef3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java @@ -21,9 +21,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; import static android.view.DisplayCutout.fromBoundingRect; +import static android.view.InsetsState.ITYPE_IME; +import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -34,6 +35,8 @@ import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import android.view.DisplayInfo; import android.view.Gravity; +import android.view.InsetsSource; +import android.view.InsetsState; import android.view.WindowManager; import androidx.test.filters.FlakyTest; @@ -57,7 +60,6 @@ import org.mockito.Mockito; @RunWith(WindowTestRunner.class) public class WindowFrameTests extends WindowTestsBase { - private final Rect mEmptyRect = new Rect(); private DisplayContent mTestDisplayContent; @Before @@ -76,18 +78,6 @@ public class WindowFrameTests extends WindowTestsBase { assertEquals(bottom, rect.bottom); } - private void assertContentInset(WindowState w, int left, int top, int right, int bottom) { - assertRect(w.getContentInsets(), left, top, right, bottom); - } - - private void assertVisibleInset(WindowState w, int left, int top, int right, int bottom) { - assertRect(w.getVisibleInsets(), left, top, right, bottom); - } - - private void assertStableInset(WindowState w, int left, int top, int right, int bottom) { - assertRect(w.getStableInsets(), left, top, right, bottom); - } - private void assertFrame(WindowState w, Rect frame) { assertEquals(w.getFrame(), frame); } @@ -100,82 +90,8 @@ public class WindowFrameTests extends WindowTestsBase { assertRect(w.getRelativeFrame(), left, top, right, bottom); } - private void assertContentFrame(WindowState w, Rect expectedRect) { - assertRect(w.getContentFrame(), expectedRect.left, expectedRect.top, expectedRect.right, - expectedRect.bottom); - } - - private void assertVisibleFrame(WindowState w, Rect expectedRect) { - assertRect(w.getVisibleFrame(), expectedRect.left, expectedRect.top, expectedRect.right, - expectedRect.bottom); - } - - private void assertStableFrame(WindowState w, Rect expectedRect) { - assertRect(w.getStableFrame(), expectedRect.left, expectedRect.top, expectedRect.right, - expectedRect.bottom); - } - @Test - public void testLayoutInFullscreenTaskInsets() { - // fullscreen task doesn't use bounds for computeFrame - WindowState w = createWindow(); - w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; - - final int bottomContentInset = 100; - final int topContentInset = 50; - final int bottomVisibleInset = 30; - final int topVisibleInset = 70; - final int leftStableInset = 20; - final int rightStableInset = 90; - - // With no insets or system decor all the frames incoming from PhoneWindowManager - // are identical. - final Rect pf = new Rect(0, 0, 1000, 1000); - final Rect df = pf; - final Rect of = df; - final Rect cf = new Rect(pf); - // Produce some insets - cf.top += 50; - cf.bottom -= 100; - final Rect vf = new Rect(pf); - vf.top += topVisibleInset; - vf.bottom -= bottomVisibleInset; - final Rect sf = new Rect(pf); - sf.left += leftStableInset; - sf.right -= rightStableInset; - - final Rect dcf = pf; - // When mFrame extends past cf, the content insets are - // the difference between mFrame and ContentFrame. Visible - // and stable frames work the same way. - w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf); - w.computeFrame(); - assertFrame(w, 0, 0, 1000, 1000); - assertRelFrame(w, 0, 0, 1000, 1000); - assertContentInset(w, 0, topContentInset, 0, bottomContentInset); - assertVisibleInset(w, 0, topVisibleInset, 0, bottomVisibleInset); - assertStableInset(w, leftStableInset, 0, rightStableInset, 0); - assertContentFrame(w, cf); - assertVisibleFrame(w, vf); - assertStableFrame(w, sf); - // On the other hand getFrame() doesn't extend past cf we won't get any insets - w.mAttrs.x = 100; - w.mAttrs.y = 100; - w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT - w.mRequestedWidth = 100; - w.mRequestedHeight = 100; - w.computeFrame(); - assertFrame(w, 100, 100, 200, 200); - assertRelFrame(w, 100, 100, 200, 200); - assertContentInset(w, 0, 0, 0, 0); - // In this case the frames are shrunk to the window frame. - assertContentFrame(w, w.getFrame()); - assertVisibleFrame(w, w.getFrame()); - assertStableFrame(w, w.getFrame()); - } - - @Test - public void testLayoutInFullscreenTaskNoInsets() { + public void testLayoutInFullscreenTask() { // fullscreen task doesn't use bounds for computeFrame WindowState w = createWindow(); w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; @@ -186,7 +102,7 @@ public class WindowFrameTests extends WindowTestsBase { // Here the window has FILL_PARENT, FILL_PARENT // so we expect it to fill the entire available frame. - w.getWindowFrames().setFrames(pf, pf, pf, pf, pf, pf); + w.getWindowFrames().setFrames(pf, pf); w.computeFrame(); assertFrame(w, 0, 0, 1000, 1000); assertRelFrame(w, 0, 0, 1000, 1000); @@ -278,76 +194,24 @@ public class WindowFrameTests extends WindowTestsBase { final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight); final WindowFrames windowFrames = w.getWindowFrames(); - windowFrames.setFrames(pf, pf, pf, pf, pf, pf); + windowFrames.setFrames(pf, pf); w.computeFrame(); // For non fullscreen tasks the containing frame is based off the // task bounds not the parent frame. assertEquals(resolvedTaskBounds, w.getFrame()); assertEquals(0, w.getRelativeFrame().left); assertEquals(0, w.getRelativeFrame().top); - assertContentFrame(w, resolvedTaskBounds); - assertContentInset(w, 0, 0, 0, 0); pf.set(0, 0, logicalWidth, logicalHeight); // We still produce insets against the containing frame the same way. final int cfRight = logicalWidth / 2; final int cfBottom = logicalHeight / 2; final Rect cf = new Rect(0, 0, cfRight, cfBottom); - windowFrames.setFrames(pf, pf, cf, cf, pf, cf); + windowFrames.setFrames(pf, pf); w.computeFrame(); assertEquals(resolvedTaskBounds, w.getFrame()); assertEquals(0, w.getRelativeFrame().left); assertEquals(0, w.getRelativeFrame().top); - int contentInsetRight = resolvedTaskBounds.right - cfRight; - int contentInsetBottom = resolvedTaskBounds.bottom - cfBottom; - assertContentInset(w, 0, 0, contentInsetRight, contentInsetBottom); - assertContentFrame(w, new Rect(resolvedTaskBounds.left, resolvedTaskBounds.top, - resolvedTaskBounds.right - contentInsetRight, - resolvedTaskBounds.bottom - contentInsetBottom)); - } - - @Test - @FlakyTest(bugId = 130388666) - public void testCalculatePolicyCrop() { - final WindowState w = createWindow(); - w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; - - final DisplayInfo displayInfo = w.getDisplayContent().getDisplayInfo(); - final int logicalWidth = displayInfo.logicalWidth; - final int logicalHeight = displayInfo.logicalHeight; - final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight); - final Rect df = pf; - final Rect cf = new Rect(pf); - // Produce some insets - cf.top += displayInfo.logicalWidth / 10; - cf.bottom -= displayInfo.logicalWidth / 5; - final Rect vf = cf; - final Rect sf = vf; - // We use a decor content frame with insets to produce cropping. - Rect dcf = new Rect(cf); - - final WindowFrames windowFrames = w.getWindowFrames(); - windowFrames.setFrames(pf, df, cf, vf, dcf, sf); - w.computeFrame(); - - windowFrames.mDecorFrame.setEmpty(); - // Likewise with no decor frame we would get no crop - w.computeFrame(); - - // Now we set up a window which doesn't fill the entire decor frame. - // Normally it would be cropped to it's frame but in the case of docked resizing - // we need to account for the fact the windows surface will be made - // fullscreen and thus also make the crop fullscreen. - - windowFrames.setFrames(pf, pf, pf, pf, pf, pf); - w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; - w.mAttrs.width = logicalWidth / 2; - w.mAttrs.height = logicalHeight / 2; - w.mRequestedWidth = logicalWidth / 2; - w.mRequestedHeight = logicalHeight / 2; - w.computeFrame(); - - doReturn(true).when(w).isDockedResizing(); } @Test @@ -372,13 +236,11 @@ public class WindowFrameTests extends WindowTestsBase { final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight); final WindowFrames windowFrames = w.getWindowFrames(); - windowFrames.setFrames(pf, pf, pf, pf, pf, pf); + windowFrames.setFrames(pf, pf); w.computeFrame(); // For non fullscreen tasks the containing frame is based off the // task bounds not the parent frame. assertFrame(w, taskLeft, taskTop, taskRight, taskBottom); - assertContentFrame(w, taskBounds); - assertContentInset(w, 0, 0, 0, 0); // Now simulate switch to fullscreen for letterboxed app. final int xInset = logicalWidth / 10; @@ -390,11 +252,9 @@ public class WindowFrameTests extends WindowTestsBase { pf.set(0, 0, logicalWidth, logicalHeight); task.setWindowingMode(WINDOWING_MODE_FULLSCREEN); task.setBounds(null); - windowFrames.setFrames(pf, pf, cf, cf, pf, cf); + windowFrames.setFrames(pf, pf); w.computeFrame(); assertFrame(w, cf); - assertContentFrame(w, cf); - assertContentInset(w, 0, 0, 0, 0); } @Test @@ -411,7 +271,7 @@ public class WindowFrameTests extends WindowTestsBase { pf.width(), pf.height()); final WindowFrames windowFrames = w.getWindowFrames(); - windowFrames.setFrames(pf, pf, pf, pf, pf, pf); + windowFrames.setFrames(pf, pf); windowFrames.setDisplayCutout(cutout); w.computeFrame(); @@ -430,51 +290,52 @@ public class WindowFrameTests extends WindowTestsBase { w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP; task.setWindowingMode(WINDOWING_MODE_FREEFORM); - DisplayContent dc = mTestDisplayContent; + // Make IME attach to the window and can produce insets. + final DisplayContent dc = mTestDisplayContent; dc.mInputMethodTarget = w; WindowState mockIme = mock(WindowState.class); Mockito.doReturn(true).when(mockIme).isVisibleNow(); dc.mInputMethodWindow = mockIme; + final InsetsState state = dc.getInsetsStateController().getRawInsetsState(); + final InsetsSource imeSource = state.getSource(ITYPE_IME); + final Rect imeFrame = new Rect(state.getDisplayFrame()); + imeFrame.top = 400; + imeSource.setFrame(imeFrame); + imeSource.setVisible(true); + w.updateRequestedVisibility(state); + w.mBehindIme = true; // With no insets or system decor all the frames incoming from PhoneWindowManager // are identical. final Rect pf = new Rect(0, 0, 1000, 800); - final Rect df = pf; - final Rect of = df; - final Rect cf = new Rect(pf); - cf.bottom -= 400; - final Rect vf = new Rect(cf); - final Rect sf = new Rect(pf); - final Rect dcf = pf; // First check that it only gets moved up enough to show window. final Rect winRect = new Rect(200, 200, 300, 500); - task.setBounds(winRect); - w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf); + w.getWindowFrames().setFrames(pf, pf); w.computeFrame(); + assertFrame(w, winRect.left, imeFrame.top - winRect.height(), winRect.right, imeFrame.top); - final Rect expected = new Rect(winRect.left, cf.bottom - winRect.height(), - winRect.right, cf.bottom); - assertEquals(expected, w.getFrame()); - assertEquals(expected, w.getContentFrame()); - assertEquals(expected, w.getVisibleFrame()); - - // Now check that it won't get moved beyond the top and then has appropriate insets - winRect.bottom = 600; + // Now check that it won't get moved beyond the top + winRect.bottom = 650; task.setBounds(winRect); w.setBounds(winRect); - w.getWindowFrames().setFrames(pf, df, cf, vf, dcf, sf); + w.getWindowFrames().setFrames(pf, pf); w.computeFrame(); - assertFrame(w, winRect.left, 0, winRect.right, winRect.height()); - expected.top = 0; - expected.bottom = cf.bottom; - assertContentFrame(w, expected); - assertVisibleFrame(w, expected); + + // Now we have status bar. Check that it won't go into the status bar area. + final Rect statusBarFrame = new Rect(state.getDisplayFrame()); + statusBarFrame.bottom = 60; + state.getSource(ITYPE_STATUS_BAR).setFrame(statusBarFrame); + w.getWindowFrames().setFrames(pf, pf); + w.computeFrame(); + assertFrame(w, winRect.left, statusBarFrame.bottom, winRect.right, + statusBarFrame.bottom + winRect.height()); // Check that it's moved back without ime insets - w.getWindowFrames().setFrames(pf, df, pf, pf, dcf, sf); + state.removeSource(ITYPE_IME); + w.getWindowFrames().setFrames(pf, pf); w.computeFrame(); assertEquals(winRect, w.getFrame()); } |