Introduce InsetsSizeOverride

This is to let the insets provider provide a different size to the given
windowing typed window. This can completely replace the ime frame
provider and the old ime frame provider is migrated.

Test: The task bar can still provide correct IME insets
Test: DisplayPolicyInsetsTests
Test: WmTests
Bug: 225200928
Change-Id: I5f8c4462cdc48011efda908e0337a86cbf2a417f
This commit is contained in:
Yunfan Chen
2022-06-28 18:24:11 +09:00
parent 0251a89274
commit 14f94246f6
9 changed files with 247 additions and 140 deletions

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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());