diff options
| author | 2024-08-29 11:42:49 +0000 | |
|---|---|---|
| committer | 2024-08-29 11:48:05 +0000 | |
| commit | a0e471c1b6bcbb83729fe99391e2932e038c4c54 (patch) | |
| tree | 798906a73d7073e8326b2462723d718445c39611 | |
| parent | 0bda560523392d3a97177c0b289d4d7b4374e33f (diff) | |
Prevent IME predictive back control during hide anim
Insets control should not be granted to ImeBackAnimationController when
there is already a hide animation in progress.
Bug: 362436187
Test: InsetsControllerTest
Flag: android.view.inputmethod.predictive_back_ime
Change-Id: I6284441bc91502c74f03aa6880d0fbb0614e7781
| -rw-r--r-- | core/java/android/view/InsetsController.java | 5 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/view/InsetsControllerTest.java | 31 |
2 files changed, 35 insertions, 1 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 7c8cd932f737..7392751cd3a1 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -1307,7 +1307,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation WindowInsetsAnimationControlListener listener, boolean fromIme, long durationMs, @Nullable Interpolator interpolator, @AnimationType int animationType, boolean fromPredictiveBack) { - if ((mState.calculateUncontrollableInsetsFromFrame(mFrame) & types) != 0) { + if ((mState.calculateUncontrollableInsetsFromFrame(mFrame) & types) != 0 + || (fromPredictiveBack && ((mRequestedVisibleTypes & ime()) == 0))) { + // abort if insets are uncontrollable or if control request is from predictive back but + // there is already a hide anim in progress listener.onCancelled(null); return; } diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index ce7e85868e8c..22499aeb092c 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -1131,6 +1131,37 @@ public class InsetsControllerTest { }); } + @Test + public void testPredictiveBackControlRequestCancelledDuringImeHideAnim() { + prepareControls(); + InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { + // show ime as initial state + if (!Flags.refactorInsetsController()) { + mController.show(ime(), true /* fromIme */, ImeTracker.Token.empty()); + } else { + mController.show(ime(), false /* fromIme */, ImeTracker.Token.empty()); + } + mController.cancelExistingAnimations(); // fast forward show animation + mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); + assertTrue(mController.getState().peekSource(ID_IME).isVisible()); + + // start IME hide animation + mController.hide(ime(), true /* fromIme */, null /* statsToken */); + assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ime())); + + // start control request (for predictive back animation) + WindowInsetsAnimationControlListener listener = + mock(WindowInsetsAnimationControlListener.class); + mController.controlWindowInsetsAnimation(ime(), /*cancellationSignal*/ null, + listener, /*fromIme*/ false, /*duration*/ -1, /*interpolator*/ null, + ANIMATION_TYPE_USER, /*fromPredictiveBack*/ true); + + // verify that control request is cancelled and animation type remains HIDE + verify(listener).onCancelled(any()); + assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ime())); + }); + } + private void waitUntilNextFrame() throws Exception { final CountDownLatch latch = new CountDownLatch(1); Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT, |