diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index e4d53c64a0637..9a9396c45b667 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -575,21 +575,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting public boolean onStateChanged(InsetsState state) { - boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */) + boolean stateChanged = !mState.equals(state, true /* excludingCaptionInsets */, + false /* excludeInvisibleIme */) || !captionInsetsUnchanged(); - if (!localStateChanged && mLastDispatchedState.equals(state)) { + if (!stateChanged && mLastDispatchedState.equals(state)) { return false; } if (DEBUG) Log.d(TAG, "onStateChanged: " + state); updateState(state); + + boolean localStateChanged = !mState.equals(mLastDispatchedState, + true /* excludingCaptionInsets */, true /* excludeInvisibleIme */); mLastDispatchedState.set(state, true /* copySources */); + applyLocalVisibilityOverride(); if (localStateChanged) { - if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged"); + if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged, send state to WM: " + mState); mHost.notifyInsetsChanged(); - } - if (!mState.equals(mLastDispatchedState, true /* excludingCaptionInsets */)) { - if (DEBUG) Log.d(TAG, "onStateChanged, send state to WM: " + mState); updateRequestedState(); } return true; diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java index b0158467a17b3..15b9a93303924 100644 --- a/core/java/android/view/InsetsSource.java +++ b/core/java/android/view/InsetsSource.java @@ -191,6 +191,14 @@ public class InsetsSource implements Parcelable { @Override public boolean equals(Object o) { + return equals(o, false); + } + + /** + * @param excludeInvisibleImeFrames If {@link InsetsState#ITYPE_IME} frames should be ignored + * when IME is not visible. + */ + public boolean equals(Object o, boolean excludeInvisibleImeFrames) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -198,6 +206,7 @@ public class InsetsSource implements Parcelable { if (mType != that.mType) return false; if (mVisible != that.mVisible) return false; + if (excludeInvisibleImeFrames && !mVisible && mType == ITYPE_IME) return true; if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false; return mFrame.equals(that.mFrame); } diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index f0bca260be387..397b04e9c023b 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -555,7 +555,7 @@ public class InsetsState implements Parcelable { @Override public boolean equals(Object o) { - return equals(o, false); + return equals(o, false, false); } /** @@ -564,10 +564,13 @@ public class InsetsState implements Parcelable { * excluded. * @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but * ignore the caption insets source value. + * @param excludeInvisibleImeFrames If {@link #ITYPE_IME} frames should be ignored when IME is + * not visible. * @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise. */ @VisibleForTesting - public boolean equals(Object o, boolean excludingCaptionInsets) { + public boolean equals(Object o, boolean excludingCaptionInsets, + boolean excludeInvisibleImeFrames) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } @@ -598,7 +601,7 @@ public class InsetsState implements Parcelable { if (otherSource == null) { return false; } - if (!otherSource.equals(source)) { + if (!otherSource.equals(source, excludeInvisibleImeFrames)) { return false; } } diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index d4c256972b28a..964ae21d6086b 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -678,7 +678,8 @@ public class InsetsControllerTest { final InsetsState currentState = new InsetsState(mController.getState()); // The caption bar source should be synced with the info in mAttachInfo. assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame()); - assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/)); + assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/, + true /* excludeInvisibleIme */)); mController.setCaptionInsetsHeight(0); mController.onStateChanged(state); // The caption bar source should not be there at all, because we don't add empty diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index cd93eeb857f14..7115acfedcf6b 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -275,6 +275,15 @@ public class InsetsStateTest { assertEqualsAndHashCode(); } + @Test + public void testEquals_excludeInvisibleIme() { + mState.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_IME).setVisible(false); + mState2.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 200)); + mState2.getSource(ITYPE_IME).setVisible(false); + assertTrue(mState2.equals(mState, true, true /* excludeInvisibleIme */)); + } + @Test public void testParcelUnparcel() { mState.getSource(ITYPE_IME).setFrame(new Rect(0, 0, 100, 100)); diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 77bc37f0c2d72..bf9a784891676 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -178,6 +178,7 @@ class InsetsStateController { if (imeSource != null && imeSource.isVisible()) { imeSource = new InsetsSource(imeSource); imeSource.setVisible(false); + imeSource.setFrame(0, 0, 0, 0); state = new InsetsState(state); state.addSource(imeSource); }