diff options
9 files changed, 247 insertions, 140 deletions
diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java index 9e66f54321cc..eb8687c47bed 100644 --- a/core/java/android/view/InsetsFrameProvider.java +++ b/core/java/android/view/InsetsFrameProvider.java @@ -16,10 +16,14 @@ package android.view; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; + import android.graphics.Insets; +import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; +import java.util.Arrays; import java.util.Objects; /** @@ -52,7 +56,9 @@ public class InsetsFrameProvider implements Parcelable { public static final int SOURCE_FRAME = 2; private static final int HAS_INSETS_SIZE = 1; - private static final int HAS_IME_INSETS_SIZE = 2; + private static final int HAS_INSETS_SIZE_OVERRIDE = 2; + + private static Rect sTmpRect = new Rect(); /** * The type of insets to provide. @@ -77,29 +83,25 @@ public class InsetsFrameProvider implements Parcelable { public Insets insetsSize = null; /** - * The provided frame based on the source frame. The result will be used as the insets - * size to IME window. Only one side should be set. + * If null, the size set in insetsSize will be applied to all window types. If it contains + * element of some types, the insets reported to the window with that types will be overridden. */ - public Insets imeInsetsSize = null; + public InsetsSizeOverride[] insetsSizeOverrides = null; public InsetsFrameProvider(int type) { this(type, SOURCE_FRAME, null, null); } public InsetsFrameProvider(int type, Insets insetsSize) { - this(type, SOURCE_FRAME, insetsSize, insetsSize); - } - - public InsetsFrameProvider(int type, Insets insetsSize, Insets imeInsetsSize) { - this(type, SOURCE_FRAME, insetsSize, imeInsetsSize); + this(type, SOURCE_FRAME, insetsSize, null); } public InsetsFrameProvider(int type, int source, Insets insetsSize, - Insets imeInsetsSize) { + InsetsSizeOverride[] insetsSizeOverride) { this.type = type; this.source = source; this.insetsSize = insetsSize; - this.imeInsetsSize = imeInsetsSize; + this.insetsSizeOverrides = insetsSizeOverride; } @Override @@ -127,8 +129,8 @@ public class InsetsFrameProvider implements Parcelable { if (insetsSize != null) { sb.append(", insetsSize=").append(insetsSize); } - if (imeInsetsSize != null) { - sb.append(", imeInsetsSize=").append(imeInsetsSize); + if (insetsSizeOverrides != null) { + sb.append(", insetsSizeOverrides=").append(Arrays.toString(insetsSizeOverrides)); } sb.append("}"); return sb.toString(); @@ -141,8 +143,8 @@ public class InsetsFrameProvider implements Parcelable { if ((insetsSizeModified & HAS_INSETS_SIZE) != 0) { insetsSize = Insets.CREATOR.createFromParcel(in); } - if ((insetsSizeModified & HAS_IME_INSETS_SIZE) != 0) { - imeInsetsSize = Insets.CREATOR.createFromParcel(in); + if ((insetsSizeModified & HAS_INSETS_SIZE_OVERRIDE) != 0) { + insetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR); } } @@ -152,8 +154,8 @@ public class InsetsFrameProvider implements Parcelable { if (insetsSize != null) { insetsSizeModified |= HAS_INSETS_SIZE; } - if (imeInsetsSize != null) { - insetsSizeModified |= HAS_IME_INSETS_SIZE; + if (insetsSizeOverrides != null) { + insetsSizeModified |= HAS_INSETS_SIZE_OVERRIDE; } out.writeInt(insetsSizeModified); out.writeInt(type); @@ -161,8 +163,8 @@ public class InsetsFrameProvider implements Parcelable { if (insetsSize != null) { insetsSize.writeToParcel(out, flags); } - if (imeInsetsSize != null) { - imeInsetsSize.writeToParcel(out, flags); + if (insetsSizeOverrides != null) { + out.writeTypedArray(insetsSizeOverrides, flags); } } @@ -177,16 +179,12 @@ public class InsetsFrameProvider implements Parcelable { InsetsFrameProvider other = (InsetsFrameProvider) o; return type == other.type && source == other.source && Objects.equals(insetsSize, other.insetsSize) - && Objects.equals(imeInsetsSize, other.imeInsetsSize); + && Arrays.equals(insetsSizeOverrides, other.insetsSizeOverrides); } @Override public int hashCode() { - int result = type; - result = 31 * result + source; - result = 31 * result + (insetsSize != null ? insetsSize.hashCode() : 0); - result = 31 * result + (imeInsetsSize != null ? imeInsetsSize.hashCode() : 0); - return result; + return Objects.hash(type, source, insetsSize, Arrays.hashCode(insetsSizeOverrides)); } public static final @android.annotation.NonNull Parcelable.Creator<InsetsFrameProvider> @@ -201,5 +199,96 @@ public class InsetsFrameProvider implements Parcelable { return new InsetsFrameProvider[size]; } }; + + public static void calculateInsetsFrame(Rect displayFrame, Rect containerBounds, + Rect displayCutoutSafe, Rect inOutFrame, int source, Insets insetsSize, + @WindowManager.LayoutParams.PrivateFlags int privateFlags) { + boolean extendByCutout = false; + if (source == InsetsFrameProvider.SOURCE_DISPLAY) { + inOutFrame.set(displayFrame); + } else if (source == InsetsFrameProvider.SOURCE_CONTAINER_BOUNDS) { + inOutFrame.set(containerBounds); + } else { + extendByCutout = (privateFlags & PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT) != 0; + } + if (insetsSize == null) { + return; + } + // Only one side of the provider shall be applied. Check in the order of left - top - + // right - bottom, only the first non-zero value will be applied. + if (insetsSize.left != 0) { + inOutFrame.right = inOutFrame.left + insetsSize.left; + } else if (insetsSize.top != 0) { + inOutFrame.bottom = inOutFrame.top + insetsSize.top; + } else if (insetsSize.right != 0) { + inOutFrame.left = inOutFrame.right - insetsSize.right; + } else if (insetsSize.bottom != 0) { + inOutFrame.top = inOutFrame.bottom - insetsSize.bottom; + } else { + inOutFrame.setEmpty(); + } + + if (extendByCutout) { + WindowLayout.extendFrameByCutout(displayCutoutSafe, displayFrame, inOutFrame, sTmpRect); + } + } + + /** + * Class to describe the insets size to be provided to window with specific window type. If not + * used, same insets size will be sent as instructed in the insetsSize and source. + */ + public static class InsetsSizeOverride implements Parcelable { + public final int windowType; + public Insets insetsSize; + + protected InsetsSizeOverride(Parcel in) { + windowType = in.readInt(); + insetsSize = in.readParcelable(null, android.graphics.Insets.class); + } + + public InsetsSizeOverride(int type, Insets size) { + windowType = type; + insetsSize = size; + } + + public static final Creator<InsetsSizeOverride> CREATOR = + new Creator<InsetsSizeOverride>() { + @Override + public InsetsSizeOverride createFromParcel(Parcel in) { + return new InsetsSizeOverride(in); + } + + @Override + public InsetsSizeOverride[] newArray(int size) { + return new InsetsSizeOverride[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(windowType); + out.writeParcelable(insetsSize, flags); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(32); + sb.append("TypedInsetsSize: {"); + sb.append("windowType=").append(windowType); + sb.append(", insetsSize=").append(insetsSize); + sb.append("}"); + return sb.toString(); + } + + @Override + public int hashCode() { + return Objects.hash(windowType, insetsSize); + } + } } diff --git a/core/java/android/view/WindowLayout.java b/core/java/android/view/WindowLayout.java index 0941ee8a714f..57a0330e3c18 100644 --- a/core/java/android/view/WindowLayout.java +++ b/core/java/android/view/WindowLayout.java @@ -274,7 +274,7 @@ public class WindowLayout { } if (extendedByCutout) { - extendFrameByCutout(attrs.gravity, displayCutoutSafe, outDisplayFrame, outFrame, + extendFrameByCutout(displayCutoutSafe, outDisplayFrame, outFrame, mTempRect); } @@ -291,7 +291,7 @@ public class WindowLayout { + " requestedVisibilities=" + requestedVisibilities); } - public static void extendFrameByCutout(int gravity, Rect displayCutoutSafe, + public static void extendFrameByCutout(Rect displayCutoutSafe, Rect displayFrame, Rect inOutFrame, Rect tempRect) { if (displayCutoutSafe.contains(inOutFrame)) { return; diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 92ac389ece67..505ef30949ce 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -578,7 +578,7 @@ message InsetsSourceProviderProto { optional WindowStateProto pending_control_target = 6; optional WindowStateProto fake_control_target = 7; optional .android.view.SurfaceControlProto captured_leash = 8; - optional .android.graphics.RectProto ime_overridden_frame = 9; + optional .android.graphics.RectProto ime_overridden_frame = 9 [deprecated=true]; optional bool is_leash_ready_for_dispatching = 10; optional bool client_visible = 11; optional bool server_visible = 12; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 288777bdb324..124b8a654a78 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1362,7 +1362,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp void setInsetProvider(@InternalInsetsType int type, WindowContainer win, @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider) { - setInsetProvider(type, win, frameProvider, null /* imeFrameProvider */); + setInsetProvider(type, win, frameProvider, null /* overrideFrameProviders */); } /** @@ -1371,15 +1371,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * @param type The type of inset this window provides. * @param win The window. * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of - * the window should be taken. - * @param imeFrameProvider Function to compute the frame when dispatching insets to the IME, or - * {@code null} if the normal frame should be taken. + * the window should be taken. Only for non-WindowState providers, nav bar + * and status bar. + * @param overrideFrameProviders Functions to compute the frame when dispatching insets to the + * given window types, or {@code null} if the normal frame should + * be taken. */ void setInsetProvider(@InternalInsetsType int type, WindowContainer win, @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider, - @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> imeFrameProvider) { + @Nullable SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> + overrideFrameProviders) { mInsetsStateController.getSourceProvider(type).setWindowContainer(win, frameProvider, - imeFrameProvider); + overrideFrameProviders); } InsetsStateController getInsetsStateController() { @@ -3865,7 +3868,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer); } mInsetsStateController.getSourceProvider(ITYPE_IME).setWindowContainer(win, - mDisplayPolicy.getImeSourceFrameProvider(), null /* imeFrameProvider */); + mDisplayPolicy.getImeSourceFrameProvider(), null); computeImeTarget(true /* updateImeTarget */); updateImeControlTarget(); } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 95f76180c600..98a51a97110d 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -46,9 +46,9 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; @@ -1156,7 +1156,7 @@ public class DisplayPolicy { break; case TYPE_NAVIGATION_BAR: mNavigationBar = win; - mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win, + final TriConsumer<DisplayFrames, WindowContainer, Rect> navFrameProvider = (displayFrames, windowContainer, inOutFrame) -> { if (!mNavButtonForcedVisible) { final LayoutParams lp = @@ -1166,19 +1166,22 @@ public class DisplayPolicy { if (provider.type != ITYPE_NAVIGATION_BAR) { continue; } - calculateInsetsFrame(displayFrames, win, inOutFrame, - provider.source, provider.insetsSize, - lp.privateFlags, lp.gravity - ); + InsetsFrameProvider.calculateInsetsFrame( + displayFrames.mUnrestricted, + win.getBounds(), displayFrames.mDisplayCutoutSafe, + inOutFrame, provider.source, + provider.insetsSize, lp.privateFlags); } } inOutFrame.inset(win.mGivenContentInsets); } - }, - - (displayFrames, windowContainer, inOutFrame) -> { - // For IME, we don't modify the frame. - }); + }; + final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> imeOverride = + new SparseArray<>(); + // For IME, we don't modify the frame. + imeOverride.put(TYPE_INPUT_METHOD, null); + mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win, + navFrameProvider, imeOverride); mDisplayContent.setInsetProvider(ITYPE_BOTTOM_MANDATORY_GESTURES, win, (displayFrames, windowContainer, inOutFrame) -> { @@ -1246,25 +1249,48 @@ public class DisplayPolicy { final LayoutParams lp = win.mAttrs.forRotation(displayFrames.mRotation); final InsetsFrameProvider ifp = - lp.providedInsets[index]; - calculateInsetsFrame(displayFrames, windowContainer, - inOutFrame, ifp.source, ifp.insetsSize, - lp.privateFlags, lp.gravity); - } : null; - final TriConsumer<DisplayFrames, WindowContainer, Rect> imeFrameProvider = - provider.imeInsetsSize != null - ? (displayFrames, windowContainer, inOutFrame) -> { - inOutFrame.inset(win.mGivenContentInsets); - final LayoutParams lp = - win.mAttrs.forRotation(displayFrames.mRotation); - final InsetsFrameProvider ifp = - lp.providedInsets[index]; - calculateInsetsFrame(displayFrames, windowContainer, - inOutFrame, ifp.source, ifp.imeInsetsSize, - lp.privateFlags, lp.gravity); + win.mAttrs.forRotation(displayFrames.mRotation) + .providedInsets[index]; + InsetsFrameProvider.calculateInsetsFrame( + displayFrames.mUnrestricted, + windowContainer.getBounds(), + displayFrames.mDisplayCutoutSafe, + inOutFrame, ifp.source, + ifp.insetsSize, lp.privateFlags); } : null; + final InsetsFrameProvider.InsetsSizeOverride[] overrides = + provider.insetsSizeOverrides; + final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> + overrideProviders; + if (overrides != null) { + overrideProviders = new SparseArray<>(); + for (int j = overrides.length - 1; j >= 0; j--) { + final int overrideIndex = j; + final TriConsumer<DisplayFrames, WindowContainer, Rect> + overrideFrameProvider = + (displayFrames, windowContainer, inOutFrame) -> { + final LayoutParams lp = + win.mAttrs.forRotation( + displayFrames.mRotation); + final InsetsFrameProvider ifp = + win.mAttrs.providedInsets[index]; + InsetsFrameProvider.calculateInsetsFrame( + displayFrames.mUnrestricted, + windowContainer.getBounds(), + displayFrames.mDisplayCutoutSafe, + inOutFrame, ifp.source, + ifp.insetsSizeOverrides[ + overrideIndex].insetsSize, + lp.privateFlags); + }; + overrideProviders.put(overrides[j].windowType, + overrideFrameProvider); + } + } else { + overrideProviders = null; + } mDisplayContent.setInsetProvider(provider.type, win, frameProvider, - imeFrameProvider); + overrideProviders); mInsetsSourceWindowsExceptIme.add(win); } } @@ -1272,40 +1298,6 @@ public class DisplayPolicy { } } - private void calculateInsetsFrame(DisplayFrames df, WindowContainer container, Rect inOutFrame, - int source, Insets insetsSize, @LayoutParams.PrivateFlags int privateFlags, - int windowGravity) { - boolean extendByCutout = false; - if (source == InsetsFrameProvider.SOURCE_DISPLAY) { - inOutFrame.set(df.mUnrestricted); - } else if (source == InsetsFrameProvider.SOURCE_CONTAINER_BOUNDS) { - inOutFrame.set(container.getBounds()); - } else { - extendByCutout = (privateFlags & PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT) != 0; - } - if (insetsSize == null) { - return; - } - // Only one side of the provider shall be applied. Check in the order of left - top - - // right - bottom, only the first non-zero value will be applied. - if (insetsSize.left != 0) { - inOutFrame.right = inOutFrame.left + insetsSize.left; - } else if (insetsSize.top != 0) { - inOutFrame.bottom = inOutFrame.top + insetsSize.top; - } else if (insetsSize.right != 0) { - inOutFrame.left = inOutFrame.right - insetsSize.right; - } else if (insetsSize.bottom != 0) { - inOutFrame.top = inOutFrame.bottom - insetsSize.bottom; - } else { - inOutFrame.setEmpty(); - } - - if (extendByCutout) { - WindowLayout.extendFrameByCutout(windowGravity, df.mDisplayCutoutSafe, - df.mUnrestricted, inOutFrame, sTmpRect); - } - } - @WindowManagerPolicy.AltBarPosition private int getAltBarPosition(WindowManager.LayoutParams params) { switch (params.gravity) { diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index ee1ff2cd61ff..620a56d18dcd 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -289,7 +289,7 @@ class InsetsPolicy { // contains all insets types. final InsetsState originalState = mDisplayContent.getInsetsPolicy() .enforceInsetsPolicyForTarget(type, WINDOWING_MODE_FULLSCREEN, alwaysOnTop, - mStateController.getRawInsetsState()); + attrs.type, mStateController.getRawInsetsState()); InsetsState state = adjustVisibilityForTransientTypes(originalState); return adjustInsetsForRoundedCorners(token, state, state == originalState); } @@ -351,12 +351,13 @@ class InsetsPolicy { * @param type the inset type provided by the target * @param windowingMode the windowing mode of the target * @param isAlwaysOnTop is the target always on top + * @param windowType the type of the target * @param state the input inset state containing all the sources * @return The state stripped of the necessary information. */ InsetsState enforceInsetsPolicyForTarget(@InternalInsetsType int type, @WindowConfiguration.WindowingMode int windowingMode, boolean isAlwaysOnTop, - InsetsState state) { + int windowType, InsetsState state) { boolean stateCopied = false; if (type != ITYPE_INVALID) { @@ -377,21 +378,20 @@ class InsetsPolicy { if (type == ITYPE_STATUS_BAR || type == ITYPE_CLIMATE_BAR) { state.removeSource(ITYPE_CAPTION_BAR); } - - // IME needs different frames for certain cases (e.g. navigation bar in gesture nav). - if (type == ITYPE_IME) { - ArrayMap<Integer, WindowContainerInsetsSourceProvider> providers = mStateController - .getSourceProviders(); - for (int i = providers.size() - 1; i >= 0; i--) { - WindowContainerInsetsSourceProvider otherProvider = providers.valueAt(i); - if (otherProvider.overridesImeFrame()) { - InsetsSource override = - new InsetsSource( - state.getSource(otherProvider.getSource().getType())); - override.setFrame(otherProvider.getImeOverrideFrame()); - state.addSource(override); - } + } + ArrayMap<Integer, WindowContainerInsetsSourceProvider> providers = mStateController + .getSourceProviders(); + for (int i = providers.size() - 1; i >= 0; i--) { + WindowContainerInsetsSourceProvider otherProvider = providers.valueAt(i); + if (otherProvider.overridesFrame(windowType)) { + if (!stateCopied) { + state = new InsetsState(state); + stateCopied = true; } + InsetsSource override = + new InsetsSource(state.getSource(otherProvider.getSource().getType())); + override.setFrame(otherProvider.getOverriddenFrame(windowType)); + state.addSource(override); } } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 610bf0594c66..86a73c935e52 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -27,7 +27,6 @@ import static com.android.server.wm.InsetsSourceProviderProto.CONTROL_TARGET; import static com.android.server.wm.InsetsSourceProviderProto.FAKE_CONTROL; import static com.android.server.wm.InsetsSourceProviderProto.FAKE_CONTROL_TARGET; import static com.android.server.wm.InsetsSourceProviderProto.FRAME; -import static com.android.server.wm.InsetsSourceProviderProto.IME_OVERRIDDEN_FRAME; import static com.android.server.wm.InsetsSourceProviderProto.IS_LEASH_READY_FOR_DISPATCHING; import static com.android.server.wm.InsetsSourceProviderProto.PENDING_CONTROL_TARGET; import static com.android.server.wm.InsetsSourceProviderProto.SEAMLESS_ROTATING; @@ -41,6 +40,7 @@ import android.annotation.Nullable; import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; +import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import android.view.InsetsFrameProvider; import android.view.InsetsSource; @@ -78,8 +78,8 @@ abstract class InsetsSourceProvider { private @Nullable ControlAdapter mAdapter; private TriConsumer<DisplayFrames, WindowContainer, Rect> mFrameProvider; - private TriConsumer<DisplayFrames, WindowContainer, Rect> mImeFrameProvider; - private final Rect mImeOverrideFrame = new Rect(); + private SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> mOverrideFrameProviders; + private final SparseArray<Rect> mOverrideFrames = new SparseArray<Rect>(); private boolean mIsLeashReadyForDispatching; private final Rect mSourceFrame = new Rect(); private final Rect mLastSourceFrame = new Rect(); @@ -146,12 +146,15 @@ abstract class InsetsSourceProvider { * @param windowContainer The window container that links to this source. * @param frameProvider Based on display frame state and the window, calculates the resulting * frame that should be reported to clients. - * @param imeFrameProvider Based on display frame state and the window, calculates the resulting - * frame that should be reported to IME. + * This will only be used when the window container providing the insets is + * not a WindowState. + * @param overrideFrameProviders Based on display frame state and the window, calculates the + * resulting frame that should be reported to given window type. */ void setWindowContainer(@Nullable WindowContainer windowContainer, @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider, - @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> imeFrameProvider) { + @Nullable SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> + overrideFrameProviders) { if (mWindowContainer != null) { if (mControllable) { mWindowContainer.setControllableInsetProvider(null); @@ -167,8 +170,9 @@ abstract class InsetsSourceProvider { ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "InsetsSource setWin %s for type %s", windowContainer, InsetsState.typeToString(mSource.getType())); mWindowContainer = windowContainer; + // TODO: remove the frame provider for non-WindowState container. mFrameProvider = frameProvider; - mImeFrameProvider = imeFrameProvider; + mOverrideFrameProviders = overrideFrameProviders; if (windowContainer == null) { setServerVisible(false); mSource.setVisibleFrame(null); @@ -228,10 +232,25 @@ abstract class InsetsSourceProvider { } updateSourceFrameForServerVisibility(); - if (mImeFrameProvider != null) { - mImeOverrideFrame.set(frame); - mImeFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames, - mWindowContainer, mImeOverrideFrame); + if (mOverrideFrameProviders != null) { + for (int i = mOverrideFrameProviders.size() - 1; i >= 0; i--) { + final int windowType = mOverrideFrameProviders.keyAt(i); + final Rect overrideFrame; + if (mOverrideFrames.contains(windowType)) { + overrideFrame = mOverrideFrames.get(windowType); + overrideFrame.set(frame); + } else { + overrideFrame = new Rect(frame); + } + final TriConsumer<DisplayFrames, WindowContainer, Rect> provider = + mOverrideFrameProviders.get(windowType); + if (provider != null) { + mOverrideFrameProviders.get(windowType).accept( + mWindowContainer.getDisplayContent().mDisplayFrames, mWindowContainer, + overrideFrame); + } + mOverrideFrames.put(windowType, overrideFrame); + } } if (win.mGivenVisibleInsets.left != 0 || win.mGivenVisibleInsets.top != 0 @@ -552,32 +571,30 @@ abstract class InsetsSourceProvider { return mClientVisible; } - /** - * @return Whether this provider uses a different frame to dispatch to the IME. - */ - boolean overridesImeFrame() { - return mImeFrameProvider != null; + boolean overridesFrame(int windowType) { + return mOverrideFrames.contains(windowType); } - /** - * @return Rect to dispatch to the IME as frame. Only valid if {@link #overridesImeFrame()} - * returns {@code true}. - */ - Rect getImeOverrideFrame() { - return mImeOverrideFrame; + Rect getOverriddenFrame(int windowType) { + return mOverrideFrames.get(windowType); } public void dump(PrintWriter pw, String prefix) { pw.println(prefix + getClass().getSimpleName()); prefix = prefix + " "; pw.print(prefix + "mSource="); mSource.dump("", pw); + pw.print(prefix + "mSourceFrame="); + pw.println(mSourceFrame); + if (mOverrideFrames.size() > 0) { + pw.print(prefix + "mOverrideFrames="); + pw.println(mOverrideFrames); + } if (mControl != null) { pw.print(prefix + "mControl="); mControl.dump("", pw); } pw.print(prefix); pw.print("mIsLeashReadyForDispatching="); pw.print(mIsLeashReadyForDispatching); - pw.print(" mImeOverrideFrame="); pw.print(mImeOverrideFrame.toShortString()); pw.println(); if (mWindowContainer != null) { pw.print(prefix + "mWindowContainer="); @@ -621,7 +638,6 @@ abstract class InsetsSourceProvider { if (mAdapter != null && mAdapter.mCapturedLeash != null) { mAdapter.mCapturedLeash.dumpDebug(proto, CAPTURED_LEASH); } - mImeOverrideFrame.dumpDebug(proto, IME_OVERRIDDEN_FRAME); proto.write(IS_LEASH_READY_FOR_DISPATCHING, mIsLeashReadyForDispatching); proto.write(CLIENT_VISIBLE, mClientVisible); proto.write(SERVER_VISIBLE, mServerVisible); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 46091d842c2a..ba82b4117875 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1703,7 +1703,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mFrozenInsetsState != null ? mFrozenInsetsState : getMergedInsetsState(); final InsetsState insetsStateForWindow = insetsPolicy .enforceInsetsPolicyForTarget(insetTypeProvidedByWindow, - getWindowingMode(), isAlwaysOnTop(), rawInsetsState); + getWindowingMode(), isAlwaysOnTop(), mAttrs.type, rawInsetsState); return insetsPolicy.adjustInsetsForWindow(this, insetsStateForWindow, includeTransient); } 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 ffa21fadff6b..6c161cf088f7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -27,6 +27,7 @@ import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; +import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -44,12 +45,15 @@ import static org.mockito.Mockito.verify; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; +import android.util.SparseArray; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.InsetsVisibilities; import androidx.test.filters.SmallTest; +import com.android.internal.util.function.TriConsumer; + import org.junit.Test; import org.junit.runner.RunWith; @@ -269,15 +273,18 @@ public class InsetsStateControllerTest extends WindowTestsBase { @Test public void testImeForDispatch() { final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); - final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime"); + final WindowState ime = createWindow(null, TYPE_INPUT_METHOD, "ime"); // IME cannot be the IME target. ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE; WindowContainerInsetsSourceProvider statusBarProvider = getController().getSourceProvider(ITYPE_STATUS_BAR); - statusBarProvider.setWindowContainer(statusBar, null, ((displayFrames, windowState, rect) -> + final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> imeOverrideProviders = + new SparseArray<>(); + imeOverrideProviders.put(TYPE_INPUT_METHOD, ((displayFrames, windowState, rect) -> rect.set(0, 1, 2, 3))); + statusBarProvider.setWindowContainer(statusBar, null, imeOverrideProviders); getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null); statusBar.setControllableInsetProvider(statusBarProvider); statusBar.updateSourceFrame(statusBar.getFrame()); |