Merge "Only update mAboveInsetsState when necessary" into sc-dev am: 657ec55928
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13482537 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I14bce177d5ec4995578423188225bbad00ed3cec
This commit is contained in:
@@ -20,8 +20,6 @@ import static android.view.InsetsStateProto.DISPLAY_CUTOUT;
|
||||
import static android.view.InsetsStateProto.DISPLAY_FRAME;
|
||||
import static android.view.InsetsStateProto.SOURCES;
|
||||
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
|
||||
import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
|
||||
import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
|
||||
import static android.view.WindowInsets.Type.displayCutout;
|
||||
import static android.view.WindowInsets.Type.ime;
|
||||
import static android.view.WindowInsets.Type.indexOf;
|
||||
@@ -106,14 +104,11 @@ public class InsetsState implements Parcelable {
|
||||
public static final int ITYPE_NAVIGATION_BAR = 1;
|
||||
public static final int ITYPE_CAPTION_BAR = 2;
|
||||
|
||||
// The always visible types are visible to all windows regardless of the z-order.
|
||||
public static final int FIRST_ALWAYS_VISIBLE_TYPE = 3;
|
||||
public static final int ITYPE_TOP_GESTURES = FIRST_ALWAYS_VISIBLE_TYPE;
|
||||
public static final int ITYPE_TOP_GESTURES = 3;
|
||||
public static final int ITYPE_BOTTOM_GESTURES = 4;
|
||||
public static final int ITYPE_LEFT_GESTURES = 5;
|
||||
public static final int ITYPE_RIGHT_GESTURES = 6;
|
||||
|
||||
/** Additional gesture inset types that map into {@link Type.MANDATORY_SYSTEM_GESTURES}. */
|
||||
public static final int ITYPE_TOP_MANDATORY_GESTURES = 7;
|
||||
public static final int ITYPE_BOTTOM_MANDATORY_GESTURES = 8;
|
||||
public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
|
||||
@@ -123,7 +118,6 @@ public class InsetsState implements Parcelable {
|
||||
public static final int ITYPE_TOP_DISPLAY_CUTOUT = 12;
|
||||
public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 13;
|
||||
public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 14;
|
||||
public static final int LAST_ALWAYS_VISIBLE_TYPE = ITYPE_BOTTOM_DISPLAY_CUTOUT;
|
||||
|
||||
public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15;
|
||||
public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16;
|
||||
@@ -187,18 +181,6 @@ public class InsetsState implements Parcelable {
|
||||
set(copy, copySources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror the always visible sources from the other state. They will share the same object for
|
||||
* the always visible types.
|
||||
*
|
||||
* @param other the state to mirror the mirrored sources from.
|
||||
*/
|
||||
public void mirrorAlwaysVisibleInsetsSources(InsetsState other) {
|
||||
for (int type = FIRST_ALWAYS_VISIBLE_TYPE; type <= LAST_ALWAYS_VISIBLE_TYPE; type++) {
|
||||
mSources[type] = other.mSources[type];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates {@link WindowInsets} based on the current source configuration.
|
||||
*
|
||||
@@ -380,14 +362,14 @@ public class InsetsState implements Parcelable {
|
||||
processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
|
||||
insets, type);
|
||||
|
||||
if (type == MANDATORY_SYSTEM_GESTURES) {
|
||||
if (type == Type.MANDATORY_SYSTEM_GESTURES) {
|
||||
// Mandatory system gestures are also system gestures.
|
||||
// TODO: find a way to express this more generally. One option would be to define
|
||||
// Type.systemGestureInsets() as NORMAL | MANDATORY, but then we lose the
|
||||
// ability to set systemGestureInsets() independently from
|
||||
// mandatorySystemGestureInsets() in the Builder.
|
||||
processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
|
||||
insets, SYSTEM_GESTURES);
|
||||
insets, Type.SYSTEM_GESTURES);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,9 +475,14 @@ public class InsetsState implements Parcelable {
|
||||
* to the client.
|
||||
*
|
||||
* @param type The {@link InternalInsetsType} of the source to remove
|
||||
* @return {@code true} if this InsetsState was modified; {@code false} otherwise.
|
||||
*/
|
||||
public void removeSource(@InternalInsetsType int type) {
|
||||
public boolean removeSource(@InternalInsetsType int type) {
|
||||
if (mSources[type] == null) {
|
||||
return false;
|
||||
}
|
||||
mSources[type] = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,6 +539,24 @@ public class InsetsState implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the values from the other InsetsState. But for sources, only specific types of source
|
||||
* would be set.
|
||||
*
|
||||
* @param other the other InsetsState.
|
||||
* @param types the only types of sources would be set.
|
||||
*/
|
||||
public void set(InsetsState other, @InsetsType int types) {
|
||||
mDisplayFrame.set(other.mDisplayFrame);
|
||||
mDisplayCutout.set(other.mDisplayCutout);
|
||||
mRoundedCorners = other.getRoundedCorners();
|
||||
final ArraySet<Integer> t = toInternalType(types);
|
||||
for (int i = t.size() - 1; i >= 0; i--) {
|
||||
final int type = t.valueAt(i);
|
||||
mSources[type] = other.mSources[type];
|
||||
}
|
||||
}
|
||||
|
||||
public void addSource(InsetsSource source) {
|
||||
mSources[source.getType()] = source;
|
||||
}
|
||||
@@ -575,6 +580,18 @@ public class InsetsState implements Parcelable {
|
||||
if ((types & Type.CAPTION_BAR) != 0) {
|
||||
result.add(ITYPE_CAPTION_BAR);
|
||||
}
|
||||
if ((types & Type.SYSTEM_GESTURES) != 0) {
|
||||
result.add(ITYPE_LEFT_GESTURES);
|
||||
result.add(ITYPE_TOP_GESTURES);
|
||||
result.add(ITYPE_RIGHT_GESTURES);
|
||||
result.add(ITYPE_BOTTOM_GESTURES);
|
||||
}
|
||||
if ((types & Type.MANDATORY_SYSTEM_GESTURES) != 0) {
|
||||
result.add(ITYPE_LEFT_MANDATORY_GESTURES);
|
||||
result.add(ITYPE_TOP_MANDATORY_GESTURES);
|
||||
result.add(ITYPE_RIGHT_MANDATORY_GESTURES);
|
||||
result.add(ITYPE_BOTTOM_MANDATORY_GESTURES);
|
||||
}
|
||||
if ((types & Type.DISPLAY_CUTOUT) != 0) {
|
||||
result.add(ITYPE_LEFT_DISPLAY_CUTOUT);
|
||||
result.add(ITYPE_TOP_DISPLAY_CUTOUT);
|
||||
|
||||
@@ -335,7 +335,7 @@ public class RoundedCorners implements Parcelable {
|
||||
}
|
||||
if (o instanceof RoundedCorners) {
|
||||
RoundedCorners r = (RoundedCorners) o;
|
||||
return Arrays.deepEquals(mRoundedCorners, ((RoundedCorners) o).mRoundedCorners);
|
||||
return Arrays.deepEquals(mRoundedCorners, r.mRoundedCorners);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -673,10 +673,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
// Used in updating override configurations
|
||||
private final Configuration mTempConfig = new Configuration();
|
||||
|
||||
// Used in performing layout, to record the insets provided by other windows above the current
|
||||
// window.
|
||||
private InsetsState mTmpAboveInsetsState = new InsetsState();
|
||||
|
||||
/**
|
||||
* Used to prevent recursions when calling
|
||||
* {@link #ensureActivitiesVisible(ActivityRecord, int, boolean, boolean)}
|
||||
@@ -778,13 +774,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
+ " parentHidden=" + w.isParentWindowHidden());
|
||||
}
|
||||
|
||||
// Sets mAboveInsets for each window. Windows behind the window providing the insets can
|
||||
// receive the insets.
|
||||
if (!w.mAboveInsetsState.equals(mTmpAboveInsetsState)) {
|
||||
w.mAboveInsetsState.set(mTmpAboveInsetsState);
|
||||
mWinInsetsChanged.add(w);
|
||||
}
|
||||
|
||||
// If this view is GONE, then skip it -- keep the current frame, and let the caller know
|
||||
// so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
|
||||
// since that means "perform layout as normal, just don't display").
|
||||
@@ -818,16 +807,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
+ " mContainingFrame=" + w.getContainingFrame()
|
||||
+ " mDisplayFrame=" + w.getDisplayFrame());
|
||||
}
|
||||
provideInsetsByWindow(w);
|
||||
};
|
||||
|
||||
private void provideInsetsByWindow(WindowState w) {
|
||||
for (int i = 0; i < w.mProvidedInsetsSources.size(); i++) {
|
||||
final InsetsSource providedSource = w.mProvidedInsetsSources.valueAt(i);
|
||||
mTmpAboveInsetsState.addSource(providedSource);
|
||||
}
|
||||
}
|
||||
|
||||
private final Consumer<WindowState> mPerformLayoutAttached = w -> {
|
||||
if (w.mLayoutAttached) {
|
||||
if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
|
||||
@@ -2511,8 +2492,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
|
||||
void onDisplayInfoChanged() {
|
||||
final DisplayInfo info = mDisplayInfo;
|
||||
mDisplayFrames.onDisplayInfoUpdated(info, calculateDisplayCutoutForRotation(info.rotation),
|
||||
calculateRoundedCornersForRotation(info.rotation));
|
||||
if (mDisplayFrames.onDisplayInfoUpdated(info,
|
||||
calculateDisplayCutoutForRotation(info.rotation),
|
||||
calculateRoundedCornersForRotation(info.rotation))) {
|
||||
// TODO(b/161810301): Set notifyInsetsChange to true while the server no longer performs
|
||||
// layout.
|
||||
mInsetsStateController.onDisplayInfoUpdated(false /* notifyInsetsChange */);
|
||||
}
|
||||
mInputMonitor.layoutInputConsumers(info.logicalWidth, info.logicalHeight);
|
||||
mDisplayPolicy.onDisplayInfoChanged(info);
|
||||
}
|
||||
@@ -3767,8 +3753,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
// 2. Assign window layers based on the IME surface parent to make sure it is on top of the
|
||||
// app.
|
||||
assignWindowLayers(true /* setLayoutNeeded */);
|
||||
// 3. Update the IME control target to apply any inset change and animation.
|
||||
// 4. Reparent the IME container surface to either the input target app, or the IME window
|
||||
// 3. The z-order of IME might have been changed. Update the above insets state.
|
||||
mInsetsStateController.updateAboveInsetsState(
|
||||
mInputMethodWindow, true /* notifyInsetsChange */);
|
||||
// 4. Update the IME control target to apply any inset change and animation.
|
||||
// 5. Reparent the IME container surface to either the input target app, or the IME window
|
||||
// parent.
|
||||
updateImeControlTarget();
|
||||
}
|
||||
@@ -4341,14 +4330,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
+ " dh=" + mDisplayInfo.logicalHeight);
|
||||
}
|
||||
|
||||
// Used to indicate that we have processed the insets windows. This needs to be after
|
||||
// beginLayoutLw to ensure the raw insets state display related info is initialized.
|
||||
final InsetsState rawInsetsState = getInsetsStateController().getRawInsetsState();
|
||||
mTmpAboveInsetsState = new InsetsState();
|
||||
mTmpAboveInsetsState.setDisplayFrame(rawInsetsState.getDisplayFrame());
|
||||
mTmpAboveInsetsState.setDisplayCutout(rawInsetsState.getDisplayCutout());
|
||||
mTmpAboveInsetsState.mirrorAlwaysVisibleInsetsSources(rawInsetsState);
|
||||
|
||||
int seq = mLayoutSeq + 1;
|
||||
if (seq < 0) seq = 0;
|
||||
mLayoutSeq = seq;
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
|
||||
import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
|
||||
import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.graphics.Rect;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.DisplayCutout;
|
||||
@@ -70,25 +71,28 @@ public class DisplayFrames {
|
||||
* @param info the updated {@link DisplayInfo}.
|
||||
* @param displayCutout the updated {@link DisplayCutout}.
|
||||
* @param roundedCorners the updated {@link RoundedCorners}.
|
||||
* @return {@code true} if the insets state has been changed; {@code false} otherwise.
|
||||
*/
|
||||
public void onDisplayInfoUpdated(DisplayInfo info, WmDisplayCutout displayCutout,
|
||||
RoundedCorners roundedCorners) {
|
||||
mDisplayWidth = info.logicalWidth;
|
||||
mDisplayHeight = info.logicalHeight;
|
||||
public boolean onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout,
|
||||
@NonNull RoundedCorners roundedCorners) {
|
||||
mRotation = info.rotation;
|
||||
final WmDisplayCutout wmDisplayCutout =
|
||||
displayCutout != null ? displayCutout : WmDisplayCutout.NO_CUTOUT;
|
||||
|
||||
final InsetsState state = mInsetsState;
|
||||
final Rect unrestricted = mUnrestricted;
|
||||
final Rect safe = mDisplayCutoutSafe;
|
||||
final DisplayCutout cutout = wmDisplayCutout.getDisplayCutout();
|
||||
final DisplayCutout cutout = displayCutout.getDisplayCutout();
|
||||
if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight
|
||||
&& state.getDisplayCutout().equals(cutout)
|
||||
&& state.getRoundedCorners().equals(roundedCorners)) {
|
||||
return false;
|
||||
}
|
||||
mDisplayWidth = info.logicalWidth;
|
||||
mDisplayHeight = info.logicalHeight;
|
||||
final Rect unrestricted = mUnrestricted;
|
||||
unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight);
|
||||
safe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
state.setDisplayFrame(unrestricted);
|
||||
state.setDisplayCutout(cutout);
|
||||
state.setRoundedCorners(roundedCorners != null ? roundedCorners
|
||||
: RoundedCorners.NO_ROUNDED_CORNERS);
|
||||
state.setRoundedCorners(roundedCorners);
|
||||
if (!cutout.isEmpty()) {
|
||||
if (cutout.getSafeInsetLeft() > 0) {
|
||||
safe.left = unrestricted.left + cutout.getSafeInsetLeft();
|
||||
@@ -116,6 +120,7 @@ public class DisplayFrames {
|
||||
state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
|
||||
state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
|
||||
|
||||
@@ -27,6 +27,9 @@ import static android.view.InsetsState.ITYPE_IME;
|
||||
import static android.view.InsetsState.ITYPE_INVALID;
|
||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||
import static android.view.WindowInsets.Type.displayCutout;
|
||||
import static android.view.WindowInsets.Type.mandatorySystemGestures;
|
||||
import static android.view.WindowInsets.Type.systemGestures;
|
||||
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_STATUS_BAR;
|
||||
@@ -293,6 +296,76 @@ class InsetsStateController {
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates {@link WindowState#mAboveInsetsState} for all windows in the display while the
|
||||
* z-order of a window is changed.
|
||||
*
|
||||
* @param win The window whose z-order has changed.
|
||||
* @param notifyInsetsChange {@code true} if the clients should be notified about the change.
|
||||
*/
|
||||
void updateAboveInsetsState(WindowState win, boolean notifyInsetsChange) {
|
||||
if (win == null || win.getDisplayContent() != mDisplayContent) {
|
||||
return;
|
||||
}
|
||||
final boolean[] aboveWin = { true };
|
||||
final InsetsState aboveInsetsState = new InsetsState();
|
||||
aboveInsetsState.set(mState,
|
||||
displayCutout() | systemGestures() | mandatorySystemGestures());
|
||||
final SparseArray<InsetsSource> winProvidedSources = win.mProvidedInsetsSources;
|
||||
final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
|
||||
mDisplayContent.forAllWindows(w -> {
|
||||
if (aboveWin[0]) {
|
||||
if (w == win) {
|
||||
aboveWin[0] = false;
|
||||
if (!win.mAboveInsetsState.equals(aboveInsetsState)) {
|
||||
win.mAboveInsetsState.set(aboveInsetsState);
|
||||
insetsChangedWindows.add(win);
|
||||
}
|
||||
return winProvidedSources.size() == 0;
|
||||
} else {
|
||||
final SparseArray<InsetsSource> providedSources = w.mProvidedInsetsSources;
|
||||
for (int i = providedSources.size() - 1; i >= 0; i--) {
|
||||
aboveInsetsState.addSource(providedSources.valueAt(i));
|
||||
}
|
||||
if (winProvidedSources.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
boolean changed = false;
|
||||
for (int i = winProvidedSources.size() - 1; i >= 0; i--) {
|
||||
changed |= w.mAboveInsetsState.removeSource(winProvidedSources.keyAt(i));
|
||||
}
|
||||
if (changed) {
|
||||
insetsChangedWindows.add(w);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = winProvidedSources.size() - 1; i >= 0; i--) {
|
||||
w.mAboveInsetsState.addSource(winProvidedSources.valueAt(i));
|
||||
}
|
||||
insetsChangedWindows.add(w);
|
||||
}
|
||||
return false;
|
||||
}, true /* traverseTopToBottom */);
|
||||
if (notifyInsetsChange) {
|
||||
for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
|
||||
mDispatchInsetsChanged.accept(insetsChangedWindows.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onDisplayInfoUpdated(boolean notifyInsetsChange) {
|
||||
final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
|
||||
mDisplayContent.forAllWindows(w -> {
|
||||
w.mAboveInsetsState.set(mState, displayCutout());
|
||||
insetsChangedWindows.add(w);
|
||||
}, true /* traverseTopToBottom */);
|
||||
if (notifyInsetsChange) {
|
||||
for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
|
||||
mDispatchInsetsChanged.accept(insetsChangedWindows.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onInsetsModified(InsetsControlTarget caller) {
|
||||
boolean changed = false;
|
||||
for (int i = mProviders.size() - 1; i >= 0; i--) {
|
||||
|
||||
@@ -1881,6 +1881,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
displayContent.sendNewConfiguration();
|
||||
}
|
||||
|
||||
// This window doesn't have a frame yet. Don't let this window cause the insets change.
|
||||
displayContent.getInsetsStateController().updateAboveInsetsState(
|
||||
win, false /* notifyInsetsChanged */);
|
||||
|
||||
getInsetsSourceControls(win, outActiveControls);
|
||||
}
|
||||
|
||||
|
||||
@@ -211,11 +211,11 @@ import android.os.Trace;
|
||||
import android.os.WorkSource;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.MergedConfiguration;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.Display;
|
||||
@@ -651,12 +651,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
/**
|
||||
* The insets state of sources provided by windows above the current window.
|
||||
*/
|
||||
InsetsState mAboveInsetsState = new InsetsState();
|
||||
final InsetsState mAboveInsetsState = new InsetsState();
|
||||
|
||||
/**
|
||||
* The insets sources provided by this window.
|
||||
*/
|
||||
ArrayMap<Integer, InsetsSource> mProvidedInsetsSources = new ArrayMap<>();
|
||||
final SparseArray<InsetsSource> mProvidedInsetsSources = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Surface insets from the previous call to relayout(), used to track
|
||||
@@ -2202,7 +2202,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
void removeImmediately() {
|
||||
super.removeImmediately();
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
|
||||
// insets state with the global one.
|
||||
final InsetsState insetsState =
|
||||
win.getDisplayContent().getInsetsStateController().getRawInsetsState();
|
||||
win.mAboveInsetsState = insetsState;
|
||||
win.mAboveInsetsState.set(insetsState);
|
||||
}
|
||||
|
||||
public void setRotation(int rotation, boolean includingWindows) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
||||
|
||||
import static android.view.InsetsState.ITYPE_IME;
|
||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
@@ -37,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
|
||||
|
||||
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
|
||||
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
|
||||
import static com.android.server.wm.utils.WmDisplayCutout.NO_CUTOUT;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -300,9 +302,9 @@ public class DisplayPolicyTests extends WindowTestsBase {
|
||||
displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
|
||||
mNavBarWindow.getControllableInsetProvider().setServerVisible(true);
|
||||
final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
|
||||
mImeWindow.mAboveInsetsState = state;
|
||||
mImeWindow.mAboveInsetsState.set(state);
|
||||
mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(),
|
||||
state, displayInfo, null /* displayCutout */, null /* roundedCorners*/);
|
||||
state, displayInfo, NO_CUTOUT, NO_ROUNDED_CORNERS);
|
||||
|
||||
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
|
||||
mImeWindow.mAttrs.setFitInsetsSides(Side.all() & ~Side.BOTTOM);
|
||||
|
||||
@@ -117,7 +117,7 @@ public class DisplayPolicyTestsBase extends WindowTestsBase {
|
||||
static Pair<DisplayInfo, WmDisplayCutout> displayInfoAndCutoutForRotation(int rotation,
|
||||
boolean withDisplayCutout, boolean isLongEdgeCutout) {
|
||||
final DisplayInfo info = new DisplayInfo();
|
||||
WmDisplayCutout cutout = null;
|
||||
WmDisplayCutout cutout = WmDisplayCutout.NO_CUTOUT;
|
||||
|
||||
final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270;
|
||||
info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
|
||||
|
||||
@@ -32,13 +32,14 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
|
||||
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -208,7 +209,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame());
|
||||
|
||||
// Make sure app got notified.
|
||||
verify(app, atLeast(1)).notifyInsetsChanged();
|
||||
verify(app, atLeastOnce()).notifyInsetsChanged();
|
||||
|
||||
// app will get visible IME insets while below IME.
|
||||
assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
|
||||
@@ -336,6 +337,92 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAboveInsetsState_provideInsets() {
|
||||
final WindowState app = createTestWindow("app");
|
||||
final WindowState statusBar = createTestWindow("statusBar");
|
||||
final WindowState navBar = createTestWindow("navBar");
|
||||
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
|
||||
assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
|
||||
getController().updateAboveInsetsState(statusBar, true /* notifyInsetsChange */);
|
||||
|
||||
assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
|
||||
verify(app, atLeastOnce()).notifyInsetsChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAboveInsetsState_receiveInsets() {
|
||||
final WindowState app = createTestWindow("app");
|
||||
final WindowState statusBar = createTestWindow("statusBar");
|
||||
final WindowState navBar = createTestWindow("navBar");
|
||||
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
|
||||
|
||||
assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
|
||||
|
||||
getController().updateAboveInsetsState(app, true /* notifyInsetsChange */);
|
||||
|
||||
assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
|
||||
|
||||
verify(app, atLeastOnce()).notifyInsetsChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAboveInsetsState_zOrderChanged() {
|
||||
final WindowState ime = createTestWindow("ime");
|
||||
final WindowState app = createTestWindow("app");
|
||||
final WindowState statusBar = createTestWindow("statusBar");
|
||||
final WindowState navBar = createTestWindow("navBar");
|
||||
|
||||
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
|
||||
getController().getSourceProvider(ITYPE_IME).setClientVisible(true);
|
||||
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
|
||||
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
|
||||
getController().updateAboveInsetsState(ime, false /* notifyInsetsChange */);
|
||||
getController().updateAboveInsetsState(statusBar, false /* notifyInsetsChange */);
|
||||
getController().updateAboveInsetsState(navBar, false /* notifyInsetsChange */);
|
||||
|
||||
// ime is below others.
|
||||
assertNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
|
||||
assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
|
||||
assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
|
||||
assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
|
||||
|
||||
ime.getParent().positionChildAt(POSITION_TOP, ime, true /* includingParents */);
|
||||
getController().updateAboveInsetsState(ime, true /* notifyInsetsChange */);
|
||||
|
||||
// ime is above others.
|
||||
assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
|
||||
assertNotNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
|
||||
assertNotNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
|
||||
assertNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
|
||||
assertNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
|
||||
|
||||
verify(ime, atLeastOnce()).notifyInsetsChanged();
|
||||
verify(app, atLeastOnce()).notifyInsetsChanged();
|
||||
verify(statusBar, atLeastOnce()).notifyInsetsChanged();
|
||||
verify(navBar, atLeastOnce()).notifyInsetsChanged();
|
||||
}
|
||||
|
||||
private WindowState createTestWindow(String name) {
|
||||
final WindowState win = createWindow(null, TYPE_APPLICATION, name);
|
||||
win.setHasSurface(true);
|
||||
spyOn(win);
|
||||
return win;
|
||||
}
|
||||
|
||||
private InsetsStateController getController() {
|
||||
return mDisplayContent.getInsetsStateController();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user