Loading core/java/android/view/InsetsState.java +39 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. * Loading Loading @@ -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); } } Loading Loading @@ -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; } /** Loading Loading @@ -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; } Loading @@ -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); Loading core/java/android/view/RoundedCorners.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading services/core/java/com/android/server/wm/DisplayContent.java +12 −31 Original line number Diff line number Diff line Loading @@ -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)} Loading Loading @@ -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"). Loading Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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(); } Loading Loading @@ -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; Loading services/core/java/com/android/server/wm/DisplayFrames.java +15 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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) { Loading services/core/java/com/android/server/wm/InsetsStateController.java +73 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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--) { Loading Loading
core/java/android/view/InsetsState.java +39 −22 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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. * Loading Loading @@ -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); } } Loading Loading @@ -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; } /** Loading Loading @@ -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; } Loading @@ -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); Loading
core/java/android/view/RoundedCorners.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; } Loading
services/core/java/com/android/server/wm/DisplayContent.java +12 −31 Original line number Diff line number Diff line Loading @@ -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)} Loading Loading @@ -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"). Loading Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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(); } Loading Loading @@ -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; Loading
services/core/java/com/android/server/wm/DisplayFrames.java +15 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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) { Loading
services/core/java/com/android/server/wm/InsetsStateController.java +73 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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--) { Loading