summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Johannes Gallmann <gallmann@google.com> 2024-08-29 11:42:49 +0000
committer Johannes Gallmann <gallmann@google.com> 2024-08-29 11:48:05 +0000
commita0e471c1b6bcbb83729fe99391e2932e038c4c54 (patch)
tree798906a73d7073e8326b2462723d718445c39611
parent0bda560523392d3a97177c0b289d4d7b4374e33f (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.java5
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java31
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,