Merge "Introduce InsetsSizeOverride" into tm-qpr-dev am: dd1b8480de

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19095354

Change-Id: I8784d9ebb838c7a906fb61119223a92e669f090f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Yunfan Chen
2022-07-13 03:14:29 +00:00
committed by Automerger Merge Worker
9 changed files with 247 additions and 140 deletions

View File

@@ -16,10 +16,14 @@
package android.view; package android.view;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT;
import android.graphics.Insets; import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
/** /**
@@ -52,7 +56,9 @@ public class InsetsFrameProvider implements Parcelable {
public static final int SOURCE_FRAME = 2; public static final int SOURCE_FRAME = 2;
private static final int HAS_INSETS_SIZE = 1; 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. * The type of insets to provide.
@@ -77,29 +83,25 @@ public class InsetsFrameProvider implements Parcelable {
public Insets insetsSize = null; public Insets insetsSize = null;
/** /**
* The provided frame based on the source frame. The result will be used as the insets * If null, the size set in insetsSize will be applied to all window types. If it contains
* size to IME window. Only one side should be set. * 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) { public InsetsFrameProvider(int type) {
this(type, SOURCE_FRAME, null, null); this(type, SOURCE_FRAME, null, null);
} }
public InsetsFrameProvider(int type, Insets insetsSize) { public InsetsFrameProvider(int type, Insets insetsSize) {
this(type, SOURCE_FRAME, insetsSize, insetsSize); this(type, SOURCE_FRAME, insetsSize, null);
}
public InsetsFrameProvider(int type, Insets insetsSize, Insets imeInsetsSize) {
this(type, SOURCE_FRAME, insetsSize, imeInsetsSize);
} }
public InsetsFrameProvider(int type, int source, Insets insetsSize, public InsetsFrameProvider(int type, int source, Insets insetsSize,
Insets imeInsetsSize) { InsetsSizeOverride[] insetsSizeOverride) {
this.type = type; this.type = type;
this.source = source; this.source = source;
this.insetsSize = insetsSize; this.insetsSize = insetsSize;
this.imeInsetsSize = imeInsetsSize; this.insetsSizeOverrides = insetsSizeOverride;
} }
@Override @Override
@@ -127,8 +129,8 @@ public class InsetsFrameProvider implements Parcelable {
if (insetsSize != null) { if (insetsSize != null) {
sb.append(", insetsSize=").append(insetsSize); sb.append(", insetsSize=").append(insetsSize);
} }
if (imeInsetsSize != null) { if (insetsSizeOverrides != null) {
sb.append(", imeInsetsSize=").append(imeInsetsSize); sb.append(", insetsSizeOverrides=").append(Arrays.toString(insetsSizeOverrides));
} }
sb.append("}"); sb.append("}");
return sb.toString(); return sb.toString();
@@ -141,8 +143,8 @@ public class InsetsFrameProvider implements Parcelable {
if ((insetsSizeModified & HAS_INSETS_SIZE) != 0) { if ((insetsSizeModified & HAS_INSETS_SIZE) != 0) {
insetsSize = Insets.CREATOR.createFromParcel(in); insetsSize = Insets.CREATOR.createFromParcel(in);
} }
if ((insetsSizeModified & HAS_IME_INSETS_SIZE) != 0) { if ((insetsSizeModified & HAS_INSETS_SIZE_OVERRIDE) != 0) {
imeInsetsSize = Insets.CREATOR.createFromParcel(in); insetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR);
} }
} }
@@ -152,8 +154,8 @@ public class InsetsFrameProvider implements Parcelable {
if (insetsSize != null) { if (insetsSize != null) {
insetsSizeModified |= HAS_INSETS_SIZE; insetsSizeModified |= HAS_INSETS_SIZE;
} }
if (imeInsetsSize != null) { if (insetsSizeOverrides != null) {
insetsSizeModified |= HAS_IME_INSETS_SIZE; insetsSizeModified |= HAS_INSETS_SIZE_OVERRIDE;
} }
out.writeInt(insetsSizeModified); out.writeInt(insetsSizeModified);
out.writeInt(type); out.writeInt(type);
@@ -161,8 +163,8 @@ public class InsetsFrameProvider implements Parcelable {
if (insetsSize != null) { if (insetsSize != null) {
insetsSize.writeToParcel(out, flags); insetsSize.writeToParcel(out, flags);
} }
if (imeInsetsSize != null) { if (insetsSizeOverrides != null) {
imeInsetsSize.writeToParcel(out, flags); out.writeTypedArray(insetsSizeOverrides, flags);
} }
} }
@@ -177,16 +179,12 @@ public class InsetsFrameProvider implements Parcelable {
InsetsFrameProvider other = (InsetsFrameProvider) o; InsetsFrameProvider other = (InsetsFrameProvider) o;
return type == other.type && source == other.source return type == other.type && source == other.source
&& Objects.equals(insetsSize, other.insetsSize) && Objects.equals(insetsSize, other.insetsSize)
&& Objects.equals(imeInsetsSize, other.imeInsetsSize); && Arrays.equals(insetsSizeOverrides, other.insetsSizeOverrides);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = type; return Objects.hash(type, source, insetsSize, Arrays.hashCode(insetsSizeOverrides));
result = 31 * result + source;
result = 31 * result + (insetsSize != null ? insetsSize.hashCode() : 0);
result = 31 * result + (imeInsetsSize != null ? imeInsetsSize.hashCode() : 0);
return result;
} }
public static final @android.annotation.NonNull Parcelable.Creator<InsetsFrameProvider> public static final @android.annotation.NonNull Parcelable.Creator<InsetsFrameProvider>
@@ -201,5 +199,96 @@ public class InsetsFrameProvider implements Parcelable {
return new InsetsFrameProvider[size]; 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) { if (extendedByCutout) {
extendFrameByCutout(attrs.gravity, displayCutoutSafe, outDisplayFrame, outFrame, extendFrameByCutout(displayCutoutSafe, outDisplayFrame, outFrame,
mTempRect); mTempRect);
} }
@@ -291,7 +291,7 @@ public class WindowLayout {
+ " requestedVisibilities=" + requestedVisibilities); + " requestedVisibilities=" + requestedVisibilities);
} }
public static void extendFrameByCutout(int gravity, Rect displayCutoutSafe, public static void extendFrameByCutout(Rect displayCutoutSafe,
Rect displayFrame, Rect inOutFrame, Rect tempRect) { Rect displayFrame, Rect inOutFrame, Rect tempRect) {
if (displayCutoutSafe.contains(inOutFrame)) { if (displayCutoutSafe.contains(inOutFrame)) {
return; return;

View File

@@ -578,7 +578,7 @@ message InsetsSourceProviderProto {
optional WindowStateProto pending_control_target = 6; optional WindowStateProto pending_control_target = 6;
optional WindowStateProto fake_control_target = 7; optional WindowStateProto fake_control_target = 7;
optional .android.view.SurfaceControlProto captured_leash = 8; 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 is_leash_ready_for_dispatching = 10;
optional bool client_visible = 11; optional bool client_visible = 11;
optional bool server_visible = 12; 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, void setInsetProvider(@InternalInsetsType int type, WindowContainer win,
@Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider) { @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 type The type of inset this window provides.
* @param win The window. * @param win The window.
* @param frameProvider Function to compute the frame, or {@code null} if the just the frame of * @param frameProvider Function to compute the frame, or {@code null} if the just the frame of
* the window should be taken. * the window should be taken. Only for non-WindowState providers, nav bar
* @param imeFrameProvider Function to compute the frame when dispatching insets to the IME, or * and status bar.
* {@code null} if the normal frame should be taken. * @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, void setInsetProvider(@InternalInsetsType int type, WindowContainer win,
@Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider, @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, mInsetsStateController.getSourceProvider(type).setWindowContainer(win, frameProvider,
imeFrameProvider); overrideFrameProviders);
} }
InsetsStateController getInsetsStateController() { InsetsStateController getInsetsStateController() {
@@ -3865,7 +3868,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer); mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer);
} }
mInsetsStateController.getSourceProvider(ITYPE_IME).setWindowContainer(win, mInsetsStateController.getSourceProvider(ITYPE_IME).setWindowContainer(win,
mDisplayPolicy.getImeSourceFrameProvider(), null /* imeFrameProvider */); mDisplayPolicy.getImeSourceFrameProvider(), null);
computeImeTarget(true /* updateImeTarget */); computeImeTarget(true /* updateImeTarget */);
updateImeControlTarget(); 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.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_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_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.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -1156,7 +1156,7 @@ public class DisplayPolicy {
break; break;
case TYPE_NAVIGATION_BAR: case TYPE_NAVIGATION_BAR:
mNavigationBar = win; mNavigationBar = win;
mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win, final TriConsumer<DisplayFrames, WindowContainer, Rect> navFrameProvider =
(displayFrames, windowContainer, inOutFrame) -> { (displayFrames, windowContainer, inOutFrame) -> {
if (!mNavButtonForcedVisible) { if (!mNavButtonForcedVisible) {
final LayoutParams lp = final LayoutParams lp =
@@ -1166,19 +1166,22 @@ public class DisplayPolicy {
if (provider.type != ITYPE_NAVIGATION_BAR) { if (provider.type != ITYPE_NAVIGATION_BAR) {
continue; continue;
} }
calculateInsetsFrame(displayFrames, win, inOutFrame, InsetsFrameProvider.calculateInsetsFrame(
provider.source, provider.insetsSize, displayFrames.mUnrestricted,
lp.privateFlags, lp.gravity win.getBounds(), displayFrames.mDisplayCutoutSafe,
); inOutFrame, provider.source,
provider.insetsSize, lp.privateFlags);
} }
} }
inOutFrame.inset(win.mGivenContentInsets); inOutFrame.inset(win.mGivenContentInsets);
} }
}, };
final SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> imeOverride =
(displayFrames, windowContainer, inOutFrame) -> { new SparseArray<>();
// For IME, we don't modify the frame. // 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, mDisplayContent.setInsetProvider(ITYPE_BOTTOM_MANDATORY_GESTURES, win,
(displayFrames, windowContainer, inOutFrame) -> { (displayFrames, windowContainer, inOutFrame) -> {
@@ -1246,25 +1249,48 @@ public class DisplayPolicy {
final LayoutParams lp = final LayoutParams lp =
win.mAttrs.forRotation(displayFrames.mRotation); win.mAttrs.forRotation(displayFrames.mRotation);
final InsetsFrameProvider ifp = final InsetsFrameProvider ifp =
lp.providedInsets[index]; win.mAttrs.forRotation(displayFrames.mRotation)
calculateInsetsFrame(displayFrames, windowContainer, .providedInsets[index];
inOutFrame, ifp.source, ifp.insetsSize, InsetsFrameProvider.calculateInsetsFrame(
lp.privateFlags, lp.gravity); displayFrames.mUnrestricted,
} : null; windowContainer.getBounds(),
final TriConsumer<DisplayFrames, WindowContainer, Rect> imeFrameProvider = displayFrames.mDisplayCutoutSafe,
provider.imeInsetsSize != null inOutFrame, ifp.source,
? (displayFrames, windowContainer, inOutFrame) -> { ifp.insetsSize, lp.privateFlags);
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);
} : null; } : 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, mDisplayContent.setInsetProvider(provider.type, win, frameProvider,
imeFrameProvider); overrideProviders);
mInsetsSourceWindowsExceptIme.add(win); 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 @WindowManagerPolicy.AltBarPosition
private int getAltBarPosition(WindowManager.LayoutParams params) { private int getAltBarPosition(WindowManager.LayoutParams params) {
switch (params.gravity) { switch (params.gravity) {

View File

@@ -289,7 +289,7 @@ class InsetsPolicy {
// contains all insets types. // contains all insets types.
final InsetsState originalState = mDisplayContent.getInsetsPolicy() final InsetsState originalState = mDisplayContent.getInsetsPolicy()
.enforceInsetsPolicyForTarget(type, WINDOWING_MODE_FULLSCREEN, alwaysOnTop, .enforceInsetsPolicyForTarget(type, WINDOWING_MODE_FULLSCREEN, alwaysOnTop,
mStateController.getRawInsetsState()); attrs.type, mStateController.getRawInsetsState());
InsetsState state = adjustVisibilityForTransientTypes(originalState); InsetsState state = adjustVisibilityForTransientTypes(originalState);
return adjustInsetsForRoundedCorners(token, state, state == originalState); return adjustInsetsForRoundedCorners(token, state, state == originalState);
} }
@@ -351,12 +351,13 @@ class InsetsPolicy {
* @param type the inset type provided by the target * @param type the inset type provided by the target
* @param windowingMode the windowing mode of the target * @param windowingMode the windowing mode of the target
* @param isAlwaysOnTop is the target always on top * @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 * @param state the input inset state containing all the sources
* @return The state stripped of the necessary information. * @return The state stripped of the necessary information.
*/ */
InsetsState enforceInsetsPolicyForTarget(@InternalInsetsType int type, InsetsState enforceInsetsPolicyForTarget(@InternalInsetsType int type,
@WindowConfiguration.WindowingMode int windowingMode, boolean isAlwaysOnTop, @WindowConfiguration.WindowingMode int windowingMode, boolean isAlwaysOnTop,
InsetsState state) { int windowType, InsetsState state) {
boolean stateCopied = false; boolean stateCopied = false;
if (type != ITYPE_INVALID) { if (type != ITYPE_INVALID) {
@@ -377,21 +378,20 @@ class InsetsPolicy {
if (type == ITYPE_STATUS_BAR || type == ITYPE_CLIMATE_BAR) { if (type == ITYPE_STATUS_BAR || type == ITYPE_CLIMATE_BAR) {
state.removeSource(ITYPE_CAPTION_BAR); state.removeSource(ITYPE_CAPTION_BAR);
} }
}
// IME needs different frames for certain cases (e.g. navigation bar in gesture nav). ArrayMap<Integer, WindowContainerInsetsSourceProvider> providers = mStateController
if (type == ITYPE_IME) { .getSourceProviders();
ArrayMap<Integer, WindowContainerInsetsSourceProvider> providers = mStateController for (int i = providers.size() - 1; i >= 0; i--) {
.getSourceProviders(); WindowContainerInsetsSourceProvider otherProvider = providers.valueAt(i);
for (int i = providers.size() - 1; i >= 0; i--) { if (otherProvider.overridesFrame(windowType)) {
WindowContainerInsetsSourceProvider otherProvider = providers.valueAt(i); if (!stateCopied) {
if (otherProvider.overridesImeFrame()) { state = new InsetsState(state);
InsetsSource override = stateCopied = true;
new InsetsSource(
state.getSource(otherProvider.getSource().getType()));
override.setFrame(otherProvider.getImeOverrideFrame());
state.addSource(override);
}
} }
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;
import static com.android.server.wm.InsetsSourceProviderProto.FAKE_CONTROL_TARGET; 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.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.IS_LEASH_READY_FOR_DISPATCHING;
import static com.android.server.wm.InsetsSourceProviderProto.PENDING_CONTROL_TARGET; import static com.android.server.wm.InsetsSourceProviderProto.PENDING_CONTROL_TARGET;
import static com.android.server.wm.InsetsSourceProviderProto.SEAMLESS_ROTATING; import static com.android.server.wm.InsetsSourceProviderProto.SEAMLESS_ROTATING;
@@ -41,6 +40,7 @@ import android.annotation.Nullable;
import android.graphics.Insets; import android.graphics.Insets;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream;
import android.view.InsetsFrameProvider; import android.view.InsetsFrameProvider;
import android.view.InsetsSource; import android.view.InsetsSource;
@@ -78,8 +78,8 @@ abstract class InsetsSourceProvider {
private @Nullable ControlAdapter mAdapter; private @Nullable ControlAdapter mAdapter;
private TriConsumer<DisplayFrames, WindowContainer, Rect> mFrameProvider; private TriConsumer<DisplayFrames, WindowContainer, Rect> mFrameProvider;
private TriConsumer<DisplayFrames, WindowContainer, Rect> mImeFrameProvider; private SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>> mOverrideFrameProviders;
private final Rect mImeOverrideFrame = new Rect(); private final SparseArray<Rect> mOverrideFrames = new SparseArray<Rect>();
private boolean mIsLeashReadyForDispatching; private boolean mIsLeashReadyForDispatching;
private final Rect mSourceFrame = new Rect(); private final Rect mSourceFrame = new Rect();
private final Rect mLastSourceFrame = 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 windowContainer The window container that links to this source.
* @param frameProvider Based on display frame state and the window, calculates the resulting * @param frameProvider Based on display frame state and the window, calculates the resulting
* frame that should be reported to clients. * frame that should be reported to clients.
* @param imeFrameProvider Based on display frame state and the window, calculates the resulting * This will only be used when the window container providing the insets is
* frame that should be reported to IME. * 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, void setWindowContainer(@Nullable WindowContainer windowContainer,
@Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider, @Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> frameProvider,
@Nullable TriConsumer<DisplayFrames, WindowContainer, Rect> imeFrameProvider) { @Nullable SparseArray<TriConsumer<DisplayFrames, WindowContainer, Rect>>
overrideFrameProviders) {
if (mWindowContainer != null) { if (mWindowContainer != null) {
if (mControllable) { if (mControllable) {
mWindowContainer.setControllableInsetProvider(null); mWindowContainer.setControllableInsetProvider(null);
@@ -167,8 +170,9 @@ abstract class InsetsSourceProvider {
ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "InsetsSource setWin %s for type %s", ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "InsetsSource setWin %s for type %s",
windowContainer, InsetsState.typeToString(mSource.getType())); windowContainer, InsetsState.typeToString(mSource.getType()));
mWindowContainer = windowContainer; mWindowContainer = windowContainer;
// TODO: remove the frame provider for non-WindowState container.
mFrameProvider = frameProvider; mFrameProvider = frameProvider;
mImeFrameProvider = imeFrameProvider; mOverrideFrameProviders = overrideFrameProviders;
if (windowContainer == null) { if (windowContainer == null) {
setServerVisible(false); setServerVisible(false);
mSource.setVisibleFrame(null); mSource.setVisibleFrame(null);
@@ -228,10 +232,25 @@ abstract class InsetsSourceProvider {
} }
updateSourceFrameForServerVisibility(); updateSourceFrameForServerVisibility();
if (mImeFrameProvider != null) { if (mOverrideFrameProviders != null) {
mImeOverrideFrame.set(frame); for (int i = mOverrideFrameProviders.size() - 1; i >= 0; i--) {
mImeFrameProvider.accept(mWindowContainer.getDisplayContent().mDisplayFrames, final int windowType = mOverrideFrameProviders.keyAt(i);
mWindowContainer, mImeOverrideFrame); 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 if (win.mGivenVisibleInsets.left != 0 || win.mGivenVisibleInsets.top != 0
@@ -552,32 +571,30 @@ abstract class InsetsSourceProvider {
return mClientVisible; return mClientVisible;
} }
/** boolean overridesFrame(int windowType) {
* @return Whether this provider uses a different frame to dispatch to the IME. return mOverrideFrames.contains(windowType);
*/
boolean overridesImeFrame() {
return mImeFrameProvider != null;
} }
/** Rect getOverriddenFrame(int windowType) {
* @return Rect to dispatch to the IME as frame. Only valid if {@link #overridesImeFrame()} return mOverrideFrames.get(windowType);
* returns {@code true}.
*/
Rect getImeOverrideFrame() {
return mImeOverrideFrame;
} }
public void dump(PrintWriter pw, String prefix) { public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + getClass().getSimpleName()); pw.println(prefix + getClass().getSimpleName());
prefix = prefix + " "; prefix = prefix + " ";
pw.print(prefix + "mSource="); mSource.dump("", pw); 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) { if (mControl != null) {
pw.print(prefix + "mControl="); pw.print(prefix + "mControl=");
mControl.dump("", pw); mControl.dump("", pw);
} }
pw.print(prefix); pw.print(prefix);
pw.print("mIsLeashReadyForDispatching="); pw.print(mIsLeashReadyForDispatching); pw.print("mIsLeashReadyForDispatching="); pw.print(mIsLeashReadyForDispatching);
pw.print(" mImeOverrideFrame="); pw.print(mImeOverrideFrame.toShortString());
pw.println(); pw.println();
if (mWindowContainer != null) { if (mWindowContainer != null) {
pw.print(prefix + "mWindowContainer="); pw.print(prefix + "mWindowContainer=");
@@ -621,7 +638,6 @@ abstract class InsetsSourceProvider {
if (mAdapter != null && mAdapter.mCapturedLeash != null) { if (mAdapter != null && mAdapter.mCapturedLeash != null) {
mAdapter.mCapturedLeash.dumpDebug(proto, CAPTURED_LEASH); mAdapter.mCapturedLeash.dumpDebug(proto, CAPTURED_LEASH);
} }
mImeOverrideFrame.dumpDebug(proto, IME_OVERRIDDEN_FRAME);
proto.write(IS_LEASH_READY_FOR_DISPATCHING, mIsLeashReadyForDispatching); proto.write(IS_LEASH_READY_FOR_DISPATCHING, mIsLeashReadyForDispatching);
proto.write(CLIENT_VISIBLE, mClientVisible); proto.write(CLIENT_VISIBLE, mClientVisible);
proto.write(SERVER_VISIBLE, mServerVisible); proto.write(SERVER_VISIBLE, mServerVisible);

View File

@@ -1703,7 +1703,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mFrozenInsetsState != null ? mFrozenInsetsState : getMergedInsetsState(); mFrozenInsetsState != null ? mFrozenInsetsState : getMergedInsetsState();
final InsetsState insetsStateForWindow = insetsPolicy final InsetsState insetsStateForWindow = insetsPolicy
.enforceInsetsPolicyForTarget(insetTypeProvidedByWindow, .enforceInsetsPolicyForTarget(insetTypeProvidedByWindow,
getWindowingMode(), isAlwaysOnTop(), rawInsetsState); getWindowingMode(), isAlwaysOnTop(), mAttrs.type, rawInsetsState);
return insetsPolicy.adjustInsetsForWindow(this, insetsStateForWindow, return insetsPolicy.adjustInsetsForWindow(this, insetsStateForWindow,
includeTransient); 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_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 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.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 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.graphics.Rect;
import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
import android.view.InsetsSourceControl; import android.view.InsetsSourceControl;
import android.view.InsetsState; import android.view.InsetsState;
import android.view.InsetsVisibilities; import android.view.InsetsVisibilities;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.internal.util.function.TriConsumer;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -269,15 +273,18 @@ public class InsetsStateControllerTest extends WindowTestsBase {
@Test @Test
public void testImeForDispatch() { public void testImeForDispatch() {
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar"); 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 cannot be the IME target.
ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE; ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
WindowContainerInsetsSourceProvider statusBarProvider = WindowContainerInsetsSourceProvider statusBarProvider =
getController().getSourceProvider(ITYPE_STATUS_BAR); 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))); rect.set(0, 1, 2, 3)));
statusBarProvider.setWindowContainer(statusBar, null, imeOverrideProviders);
getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null); getController().getSourceProvider(ITYPE_IME).setWindowContainer(ime, null, null);
statusBar.setControllableInsetProvider(statusBarProvider); statusBar.setControllableInsetProvider(statusBarProvider);
statusBar.updateSourceFrame(statusBar.getFrame()); statusBar.updateSourceFrame(statusBar.getFrame());