summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Adrian Roos <roosa@google.com> 2020-02-12 02:45:41 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-02-12 02:45:41 +0000
commite8d7ecdbb1ba81cbdb83156201e26fae1e154986 (patch)
tree139739e9b3462d6d4ad93e5b7ad1a5129b9755ad
parent524ec05bc60ed2cb973376de09372783b7a416b6 (diff)
parent3406fb97f4c5bc61727a1638b07af74aa8cca227 (diff)
Merge "Insets Animation: Add CancellationSignal to controlWindowInsetsAnimation"
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/view/InsetsController.java50
-rw-r--r--core/java/android/view/WindowInsetsController.java7
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java51
4 files changed, 92 insertions, 18 deletions
diff --git a/api/current.txt b/api/current.txt
index 88f7f03e3a28..a12da182dcab 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -55209,7 +55209,7 @@ package android.view {
}
public interface WindowInsetsController {
- method public void controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener);
+ method @NonNull public android.os.CancellationSignal controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener);
method public int getSystemBarsAppearance();
method public int getSystemBarsBehavior();
method public void hide(int);
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 54de1bb3739d..15be364c3e1c 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -32,6 +32,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.os.CancellationSignal;
import android.os.Handler;
import android.os.RemoteException;
import android.util.ArraySet;
@@ -39,7 +40,6 @@ import android.util.Log;
import android.util.Pair;
import android.util.Property;
import android.util.SparseArray;
-import android.view.InputDevice.MotionRange;
import android.view.InsetsSourceConsumer.ShowResult;
import android.view.InsetsState.InternalInsetsType;
import android.view.SurfaceControl.Transaction;
@@ -242,13 +242,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
PendingControlRequest(@InsetsType int types, WindowInsetsAnimationControlListener listener,
long durationMs, Interpolator interpolator, @AnimationType int animationType,
- @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+ @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation,
+ CancellationSignal cancellationSignal) {
this.types = types;
this.listener = listener;
this.durationMs = durationMs;
this.interpolator = interpolator;
this.animationType = animationType;
this.layoutInsetsDuringAnimation = layoutInsetsDuringAnimation;
+ this.cancellationSignal = cancellationSignal;
}
final @InsetsType int types;
@@ -257,6 +259,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
final Interpolator interpolator;
final @AnimationType int animationType;
final @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation;
+ final CancellationSignal cancellationSignal;
}
private final String TAG = "InsetsControllerImpl";
@@ -455,10 +458,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
PendingControlRequest pendingRequest = mPendingImeControlRequest;
mPendingImeControlRequest = null;
mHandler.removeCallbacks(mPendingControlTimeout);
- controlAnimationUnchecked(pendingRequest.types, pendingRequest.listener, mFrame,
+ CancellationSignal cancellationSignal = controlAnimationUnchecked(
+ pendingRequest.types,
+ pendingRequest.listener, mFrame,
true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
false /* fade */, pendingRequest.animationType,
pendingRequest.layoutInsetsDuringAnimation);
+ pendingRequest.cancellationSignal.setOnCancelListener(cancellationSignal::cancel);
return;
}
@@ -504,35 +510,39 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
@Override
- public void controlWindowInsetsAnimation(@InsetsType int types, long durationMs,
+ public CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, long durationMs,
@Nullable Interpolator interpolator,
@NonNull WindowInsetsAnimationControlListener listener) {
- controlWindowInsetsAnimation(types, listener, false /* fromIme */, durationMs, interpolator,
- ANIMATION_TYPE_USER);
+ return controlWindowInsetsAnimation(types, listener, false /* fromIme */, durationMs,
+ interpolator, ANIMATION_TYPE_USER);
}
- private void controlWindowInsetsAnimation(@InsetsType int types,
+ private CancellationSignal controlWindowInsetsAnimation(@InsetsType int types,
WindowInsetsAnimationControlListener listener, boolean fromIme, long durationMs,
@Nullable Interpolator interpolator, @AnimationType int animationType) {
// If the frame of our window doesn't span the entire display, the control API makes very
// little sense, as we don't deal with negative insets. So just cancel immediately.
if (!mState.getDisplayFrame().equals(mFrame)) {
listener.onCancelled();
- return;
+ CancellationSignal cancellationSignal = new CancellationSignal();
+ cancellationSignal.cancel();
+ return cancellationSignal;
}
- controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, interpolator,
+ return controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, interpolator,
false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types));
}
- private void controlAnimationUnchecked(@InsetsType int types,
+ private CancellationSignal controlAnimationUnchecked(@InsetsType int types,
WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme,
long durationMs, Interpolator interpolator, boolean fade,
@AnimationType int animationType,
@LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+ CancellationSignal cancellationSignal = new CancellationSignal();
if (types == 0) {
// nothing to animate.
listener.onCancelled();
- return;
+ cancellationSignal.cancel();
+ return cancellationSignal;
}
cancelExistingControllers(types);
@@ -546,21 +556,31 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (!imeReady) {
// IME isn't ready, all requested types will be animated once IME is ready
abortPendingImeControlRequest();
- mPendingImeControlRequest = new PendingControlRequest(types, listener, durationMs,
- interpolator, animationType, layoutInsetsDuringAnimation);
+ final PendingControlRequest request = new PendingControlRequest(types,
+ listener, durationMs,
+ interpolator, animationType, layoutInsetsDuringAnimation, cancellationSignal);
+ mPendingImeControlRequest = request;
mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS);
- return;
+ cancellationSignal.setOnCancelListener(() -> {
+ if (mPendingImeControlRequest == request) {
+ abortPendingImeControlRequest();
+ }
+ });
+ return cancellationSignal;
}
if (typesReady == 0) {
listener.onCancelled();
- return;
+ cancellationSignal.cancel();
+ return cancellationSignal;
}
final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(controls,
frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
layoutInsetsDuringAnimation);
mRunningAnimations.add(new RunningAnimation(controller, animationType));
+ cancellationSignal.setOnCancelListener(controller::onCancelled);
+ return cancellationSignal;
}
/**
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index ea8e73885980..27e92e559b09 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Insets;
+import android.os.CancellationSignal;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
import android.view.animation.Interpolator;
@@ -154,13 +155,15 @@ public interface WindowInsetsController {
* {@link InsetsAnimation#getInterpolatedFraction()}.
* @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the
* windows are ready to be controlled, among other callbacks.
- *
+ * @return A cancellation signal that the caller can use to cancel the request to obtain
+ * control, or once they have control, to cancel the control.
* @see InsetsAnimation#getFraction()
* @see InsetsAnimation#getInterpolatedFraction()
* @see InsetsAnimation#getInterpolator()
* @see InsetsAnimation#getDurationMillis()
*/
- void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis,
+ @NonNull
+ CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, long durationMillis,
@Nullable Interpolator interpolator,
@NonNull WindowInsetsAnimationControlListener listener);
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 2c9dba1d59fd..24fe2a0a1823 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -45,6 +45,7 @@ import android.content.Context;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.CancellationSignal;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets.Type;
@@ -516,6 +517,34 @@ public class InsetsControllerTest {
}
@Test
+ public void testCancellation_afterGainingControl() throws Exception {
+ InsetsSourceControl control =
+ new InsetsSourceControl(ITYPE_STATUS_BAR, mLeash, new Point());
+ mController.onControlsChanged(new InsetsSourceControl[] { control });
+
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ WindowInsetsAnimationControlListener mockListener =
+ mock(WindowInsetsAnimationControlListener.class);
+ CancellationSignal cancellationSignal = mController.controlWindowInsetsAnimation(
+ statusBars(), 0 /* durationMs */,
+ new LinearInterpolator(), mockListener);
+
+ // Ready gets deferred until next predraw
+ mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+ verify(mockListener).onReady(any(), anyInt());
+
+ cancellationSignal.cancel();
+ verify(mockListener).onCancelled();
+ });
+ waitUntilNextFrame();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
+ @Test
public void testControlImeNotReady() {
prepareControls();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
@@ -580,6 +609,28 @@ public class InsetsControllerTest {
});
}
+ @Test
+ public void testControlImeNotReady_cancel() {
+ prepareControls();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ WindowInsetsAnimationControlListener listener =
+ mock(WindowInsetsAnimationControlListener.class);
+ mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener)
+ .cancel();
+
+ verify(listener).onCancelled();
+
+ // Ready gets deferred until next predraw
+ mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+ verify(listener, never()).onReady(any(), anyInt());
+
+ // Pretend that timeout is happening
+ mTestClock.fastForward(2500);
+ mTestHandler.timeAdvance();
+ });
+ }
+
private void waitUntilNextFrame() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,