diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index bb5dacc89bc2a..88d7dff4ff1ac 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -114,6 +114,7 @@ import android.os.UserHandle; import android.util.ArraySet; import android.util.PrintWriterPrinter; import android.util.Slog; +import android.util.SparseArray; import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; @@ -1151,9 +1152,8 @@ public class DisplayPolicy { } }, - // For IME we use regular frame. (displayFrames, windowContainer, inOutFrame) -> { - inOutFrame.set(win.getFrame()); + // For IME, we don't modify the frame. }); mDisplayContent.setInsetProvider(ITYPE_BOTTOM_MANDATORY_GESTURES, win, @@ -1488,9 +1488,30 @@ public class DisplayPolicy { displayFrames.mInsetsState, displayFrames.mDisplayCutoutSafe, displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH, UNSPECIFIED_LENGTH, win.getRequestedVisibilities(), - null /* attachedWindowFrame */, win.mGlobalScale, - sTmpClientFrames); - controller.computeSimulatedState(win, displayFrames, sTmpClientFrames.frame); + null /* attachedWindowFrame */, win.mGlobalScale, sTmpClientFrames); + final SparseArray sources = win.getProvidedInsetsSources(); + final InsetsState state = displayFrames.mInsetsState; + for (int index = sources.size() - 1; index >= 0; index--) { + final int type = sources.keyAt(index); + state.addSource(controller.getSourceProvider(type).createSimulatedSource( + displayFrames, sTmpClientFrames.frame)); + } + } + } + + // TODO(b/161810301): No one is calling this since we haven't moved window layout to the client. + // When that happens, this should be called when the display rotation is + // changed, so that we can dispatch the correct insets to all the clients + // before the insets source windows report their frames to the server. + void updateInsetsSourceFramesExceptIme(DisplayFrames displayFrames) { + for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) { + final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i); + mWindowLayout.computeFrames(win.getLayoutingAttrs(displayFrames.mRotation), + displayFrames.mInsetsState, displayFrames.mDisplayCutoutSafe, + displayFrames.mUnrestricted, win.getWindowingMode(), UNSPECIFIED_LENGTH, + UNSPECIFIED_LENGTH, win.getRequestedVisibilities(), + null /* attachedWindowFrame */, win.mGlobalScale, sTmpClientFrames); + win.updateSourceFrame(sTmpClientFrames.frame); } } @@ -1519,10 +1540,6 @@ public class DisplayPolicy { displayFrames = win.getDisplayFrames(displayFrames); final WindowManager.LayoutParams attrs = win.getLayoutingAttrs(displayFrames.mRotation); - final WindowFrames windowFrames = win.getWindowFrames(); - final Rect pf = windowFrames.mParentFrame; - final Rect df = windowFrames.mDisplayFrame; - final Rect f = windowFrames.mFrame; final Rect attachedWindowFrame = attached != null ? attached.getFrame() : null; // If this window has different LayoutParams for rotations, we cannot trust its requested @@ -1531,25 +1548,10 @@ public class DisplayPolicy { final int requestedWidth = trustedSize ? win.mRequestedWidth : UNSPECIFIED_LENGTH; final int requestedHeight = trustedSize ? win.mRequestedHeight : UNSPECIFIED_LENGTH; - sTmpLastParentFrame.set(pf); - mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe, win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight, win.getRequestedVisibilities(), attachedWindowFrame, win.mGlobalScale, sTmpClientFrames); - windowFrames.setParentFrameWasClippedByDisplayCutout( - sTmpClientFrames.isParentFrameClippedByDisplayCutout); - - if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() - + ": sim=#" + Integer.toHexString(attrs.softInputMode) - + " attach=" + attached + " type=" + attrs.type - + " flags=" + ViewDebug.flagsToString(LayoutParams.class, "flags", attrs.flags) - + " pf=" + pf.toShortString() + " df=" + df.toShortString() - + " f=" + f.toShortString()); - - if (!sTmpLastParentFrame.equals(pf)) { - windowFrames.setContentChanged(true); - } win.setFrames(sTmpClientFrames); } diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index 199517c441ad4..0d4cfa3a8128f 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -29,6 +29,7 @@ import static com.android.server.wm.WindowManagerService.H.UPDATE_MULTI_WINDOW_S import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.Rect; import android.os.Trace; import android.util.proto.ProtoOutputStream; import android.view.InsetsSource; @@ -79,8 +80,8 @@ final class ImeInsetsSourceProvider extends WindowContainerInsetsSourceProvider } @Override - void updateSourceFrame() { - super.updateSourceFrame(); + void updateSourceFrame(Rect frame) { + super.updateSourceFrame(frame); onSourceChanged(); } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 047bf2f53b687..f3f08b202feda 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -84,6 +84,7 @@ abstract class InsetsSourceProvider { private TriConsumer mImeFrameProvider; private final Rect mImeOverrideFrame = new Rect(); private boolean mIsLeashReadyForDispatching; + private final Rect mSourceFrame = new Rect(); private final Rect mLastSourceFrame = new Rect(); private final Consumer mSetLeashPositionConsumer = t -> { @@ -183,8 +184,8 @@ abstract class InsetsSourceProvider { mImeFrameProvider = imeFrameProvider; if (windowContainer == null) { setServerVisible(false); - mSource.setFrame(new Rect()); mSource.setVisibleFrame(null); + mSourceFrame.setEmpty(); } else { mWindowContainer.getProvidedInsetsSources().put(mSource.getType(), mSource); if (mControllable) { @@ -208,7 +209,7 @@ abstract class InsetsSourceProvider { * The source frame can affect the layout of other windows, so this should be called once the * window container gets laid out. */ - void updateSourceFrame() { + void updateSourceFrame(Rect frame) { if (mWindowContainer == null) { return; } @@ -230,39 +231,25 @@ abstract class InsetsSourceProvider { return; } - if (win.mGivenInsetsPending) { - // If the given insets are pending, they are not reliable for now. The source frame - // should be updated after the new given insets are sent to window manager. - return; - } - - // Make sure we set the valid source frame only when server visible is true, because the - // frame may not yet determined that server side doesn't think the window is ready to - // visible. (i.e. No surface, pending insets that were given during layout, etc..) - if (mServerVisible) { - mTmpRect.set(win.getFrame()); - if (mFrameProvider != null) { - mFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames, - mWindowContainer, mTmpRect); - } else { - mTmpRect.inset(win.mGivenContentInsets); - } + mSourceFrame.set(frame); + if (mFrameProvider != null) { + mFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames, + mWindowContainer, mSourceFrame); } else { - mTmpRect.setEmpty(); + mSourceFrame.inset(win.mGivenContentInsets); } - mSource.setFrame(mTmpRect); + updateSourceFrameForServerVisibility(); if (mImeFrameProvider != null) { - mImeOverrideFrame.set(win.getFrame()); + mImeOverrideFrame.set(frame); mImeFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames, - mWindowContainer, - mImeOverrideFrame); + mWindowContainer, mImeOverrideFrame); } if (win.mGivenVisibleInsets.left != 0 || win.mGivenVisibleInsets.top != 0 || win.mGivenVisibleInsets.right != 0 || win.mGivenVisibleInsets.bottom != 0) { - mTmpRect.set(win.getFrame()); + mTmpRect.set(frame); mTmpRect.inset(win.mGivenVisibleInsets); mSource.setVisibleFrame(mTmpRect); } else { @@ -270,13 +257,24 @@ abstract class InsetsSourceProvider { } } + private void updateSourceFrameForServerVisibility() { + // Make sure we set the valid source frame only when server visible is true, because the + // frame may not yet determined that server side doesn't think the window is ready to + // visible. (i.e. No surface, pending insets that were given during layout, etc..) + if (mServerVisible) { + mSource.setFrame(mSourceFrame); + } else { + mSource.setFrame(0, 0, 0, 0); + } + } + /** @return A new source computed by the specified window frame in the given display frames. */ - InsetsSource createSimulatedSource(DisplayFrames displayFrames, Rect winFrame) { + InsetsSource createSimulatedSource(DisplayFrames displayFrames, Rect frame) { // Don't copy visible frame because it might not be calculated in the provided display // frames and it is not significant for this usage. final InsetsSource source = new InsetsSource(mSource.getType()); source.setVisible(mSource.isVisible()); - mTmpRect.set(winFrame); + mTmpRect.set(frame); if (mFrameProvider != null) { mFrameProvider.accept(displayFrames, mWindowContainer, mTmpRect); } @@ -296,7 +294,6 @@ abstract class InsetsSourceProvider { ? windowState.wouldBeVisibleIfPolicyIgnored() && windowState.isVisibleByPolicy() : mWindowContainer.isVisibleRequested(); setServerVisible(isServerVisible); - updateSourceFrame(); if (mControl != null) { boolean changed = false; final Point position = getWindowFrameSurfacePosition(); @@ -496,6 +493,7 @@ abstract class InsetsSourceProvider { @VisibleForTesting void setServerVisible(boolean serverVisible) { mServerVisible = serverVisible; + updateSourceFrameForServerVisibility(); updateVisibility(); } diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 78608e2bf2037..a19d72e37124a 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -30,7 +30,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; import android.annotation.NonNull; import android.annotation.Nullable; -import android.graphics.Rect; import android.os.Trace; import android.util.ArrayMap; import android.util.ArraySet; @@ -204,23 +203,6 @@ class InsetsStateController { } } - /** - * Computes insets state of the insets provider window in the display frames. - * - * @param win The owner window of insets provider. - * @param displayFrames The display frames to create insets source. - * @param winFrame The frame of the insets source window. - */ - void computeSimulatedState(WindowState win, DisplayFrames displayFrames, Rect winFrame) { - final InsetsState state = displayFrames.mInsetsState; - for (int i = mProviders.size() - 1; i >= 0; i--) { - final WindowContainerInsetsSourceProvider provider = mProviders.valueAt(i); - if (provider.mWindowContainer == win) { - state.addSource(provider.createSimulatedSource(displayFrames, winFrame)); - } - } - } - boolean isFakeTarget(@InternalInsetsType int type, InsetsControlTarget target) { return mTypeFakeControlTargetMap.get(type) == target; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 08ce6817fb6d2..43e84ae911184 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2156,6 +2156,7 @@ public class WindowManagerService extends IWindowManager.Stub w.mGivenTouchableRegion.scale(w.mGlobalScale); } w.setDisplayLayoutNeeded(); + w.updateSourceFrame(w.getFrame()); mWindowPlacerLocked.performSurfacePlacement(); w.getDisplayContent().getInputMonitor().updateInputWindowsLw(true); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 9f60051e65ecb..0ee8820be4649 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -142,7 +142,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; @@ -1402,11 +1401,15 @@ class WindowState extends WindowContainer implements WindowManagerP mHaveFrame = true; final WindowFrames windowFrames = mWindowFrames; + mTmpRect.set(windowFrames.mParentFrame); windowFrames.mDisplayFrame.set(clientWindowFrames.displayFrame); windowFrames.mParentFrame.set(clientWindowFrames.parentFrame); windowFrames.mFrame.set(clientWindowFrames.frame); + windowFrames.setParentFrameWasClippedByDisplayCutout( + clientWindowFrames.isParentFrameClippedByDisplayCutout); - if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) { + if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight + || !mTmpRect.equals(windowFrames.mParentFrame)) { mLastRequestedWidth = mRequestedWidth; mLastRequestedHeight = mRequestedHeight; windowFrames.setContentChanged(true); @@ -1435,16 +1438,6 @@ class WindowState extends WindowContainer implements WindowManagerP windowFrames.mRelFrame.offsetTo(windowFrames.mFrame.left - parentLeft, windowFrames.mFrame.top - parentTop); - if (DEBUG_LAYOUT || DEBUG) { - final int pw = windowFrames.mParentFrame.width(); - final int ph = windowFrames.mParentFrame.height(); - Slog.v(TAG, "Resolving (mRequestedWidth=" - + mRequestedWidth + ", mRequestedheight=" - + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph - + "): frame=" + windowFrames.mFrame.toShortString() - + " " + mAttrs.getTitle()); - } - if (mAttrs.type == TYPE_DOCK_DIVIDER) { if (!windowFrames.mFrame.equals(windowFrames.mLastFrame)) { mMovedByResize = true; @@ -1459,9 +1452,19 @@ class WindowState extends WindowContainer implements WindowManagerP } } - // Update the source frame to provide insets to other windows during layout. - if (mControllableInsetProvider != null) { - mControllableInsetProvider.updateSourceFrame(); + updateSourceFrame(windowFrames.mFrame); + } + + void updateSourceFrame(Rect winFrame) { + if (mGivenInsetsPending) { + // The given insets are pending, and they are not reliable for now. The source frame + // should be updated after the new given insets are sent to window manager. + return; + } + final SparseArray providedSources = getProvidedInsetsSources(); + final InsetsStateController controller = getDisplayContent().getInsetsStateController(); + for (int i = providedSources.size() - 1; i >= 0; i--) { + controller.getSourceProvider(providedSources.keyAt(i)).updateSourceFrame(winFrame); } } 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 db22757cc4feb..45ae81a71c440 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -157,6 +157,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { win.getFrame().set(0, 0, 500, 100); addWindow(win); + win.updateSourceFrame(win.getFrame()); InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.onPostLayout(); @@ -185,6 +186,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { win.getFrame().set(0, 0, 500, 100); addWindow(win); + win.updateSourceFrame(win.getFrame()); mDisplayContent.getInsetsStateController().onPostLayout(); InsetsSourceProvider provider = diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 90a6918644faf..6d022262b7200 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -280,6 +280,7 @@ public class InsetsStateControllerTest extends WindowTestsBase { rect.set(0, 1, 2, 3))); getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null); statusBar.setControllableInsetProvider(statusBarProvider); + statusBar.updateSourceFrame(statusBar.getFrame()); statusBarProvider.onPostLayout(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java index 10e429250c192..e824f3d2916d0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerInsetsSourceProviderTest.java @@ -64,6 +64,7 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { statusBar.getFrame().set(0, 0, 500, 100); statusBar.mHasSurface = true; mProvider.setWindowContainer(statusBar, null, null); + mProvider.updateSourceFrame(statusBar.getFrame()); mProvider.onPostLayout(); assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame()); assertEquals(Insets.of(0, 100, 0, 0), @@ -81,6 +82,7 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { ime.mGivenVisibleInsets.set(0, 0, 0, 75); ime.mHasSurface = true; mProvider.setWindowContainer(ime, null, null); + mProvider.updateSourceFrame(ime.getFrame()); mProvider.onPostLayout(); assertEquals(new Rect(0, 0, 500, 40), mProvider.getSource().getFrame()); assertEquals(new Rect(0, 0, 500, 25), mProvider.getSource().getVisibleFrame()); @@ -96,6 +98,7 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); statusBar.getFrame().set(0, 0, 500, 100); mProvider.setWindowContainer(statusBar, null, null); + mProvider.updateSourceFrame(statusBar.getFrame()); mProvider.onPostLayout(); assertEquals(Insets.NONE, mProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */)); @@ -110,6 +113,7 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { (displayFrames, windowState, rect) -> { rect.set(10, 10, 20, 20); }, null); + mProvider.updateSourceFrame(statusBar.getFrame()); mProvider.onPostLayout(); assertEquals(new Rect(10, 10, 20, 20), mProvider.getSource().getFrame()); } @@ -181,7 +185,7 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { mImeProvider.setWindowContainer(inputMethod, null, null); mImeProvider.setServerVisible(false); mImeSource.setVisible(true); - mImeProvider.updateSourceFrame(); + mImeProvider.updateSourceFrame(inputMethod.getFrame()); assertEquals(new Rect(0, 0, 0, 0), mImeSource.getFrame()); Insets insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */); @@ -189,7 +193,7 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { mImeProvider.setServerVisible(true); mImeSource.setVisible(true); - mImeProvider.updateSourceFrame(); + mImeProvider.updateSourceFrame(inputMethod.getFrame()); assertEquals(inputMethod.getFrame(), mImeSource.getFrame()); insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500), false /* ignoreVisibility */); @@ -229,6 +233,7 @@ public class WindowContainerInsetsSourceProviderTest extends WindowTestsBase { statusBar.getFrame().set(0, 0, 500, 100); statusBar.mHasSurface = true; mProvider.setWindowContainer(statusBar, null, null); + mProvider.updateSourceFrame(statusBar.getFrame()); mProvider.onPostLayout(); assertEquals(new Rect(0, 0, 500, 100), mProvider.getSource().getFrame()); // Still apply top insets if window overlaps even if it's top doesn't exactly match