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:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user