diff options
8 files changed, 78 insertions, 86 deletions
diff --git a/api/current.txt b/api/current.txt index ff983630c76a..d944d24d2993 100644 --- a/api/current.txt +++ b/api/current.txt @@ -55583,7 +55583,7 @@ package android.view { public interface WindowInsetsController { method public void addOnControllableInsetsChangedListener(@NonNull android.view.WindowInsetsController.OnControllableInsetsChangedListener); - method public void controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @Nullable android.os.CancellationSignal, @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 b1da4cc60ad1..607886f3b13b 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -52,6 +52,7 @@ import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Preconditions; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -493,12 +494,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation PendingControlRequest pendingRequest = mPendingImeControlRequest; mPendingImeControlRequest = null; mHandler.removeCallbacks(mPendingControlTimeout); - controlAnimationUnchecked( - pendingRequest.types, pendingRequest.cancellationSignal, + 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; } @@ -544,26 +546,24 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } @Override - public void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, + public CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, long durationMs, @Nullable Interpolator interpolator, - @Nullable CancellationSignal cancellationSignal, @NonNull WindowInsetsAnimationControlListener listener) { - controlWindowInsetsAnimation(types, cancellationSignal, listener, - false /* fromIme */, durationMillis, interpolator, ANIMATION_TYPE_USER); + return controlWindowInsetsAnimation(types, listener, false /* fromIme */, durationMs, + interpolator, ANIMATION_TYPE_USER); } - private void controlWindowInsetsAnimation(@InsetsType int types, - @Nullable CancellationSignal cancellationSignal, - WindowInsetsAnimationControlListener listener, - boolean fromIme, long durationMs, @Nullable Interpolator interpolator, - @AnimationType int animationType) { + private CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, + WindowInsetsAnimationControlListener listener, boolean fromIme, long durationMs, + @Nullable Interpolator interpolator, @AnimationType int animationType) { if (!checkDisplayFramesForControlling()) { listener.onCancelled(); - return; + CancellationSignal cancellationSignal = new CancellationSignal(); + cancellationSignal.cancel(); + return cancellationSignal; } - controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs, - interpolator, false /* fade */, animationType, - getLayoutInsetsDuringAnimationMode(types)); + return controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, interpolator, + false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types)); } private boolean checkDisplayFramesForControlling() { @@ -573,16 +573,17 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return mState.getDisplayFrame().equals(mFrame); } - private void controlAnimationUnchecked(@InsetsType int types, - @Nullable CancellationSignal cancellationSignal, + 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); mLastStartedAnimTypes |= types; @@ -602,28 +603,26 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation interpolator, animationType, layoutInsetsDuringAnimation, cancellationSignal); mPendingImeControlRequest = request; mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS); - if (cancellationSignal != null) { - cancellationSignal.setOnCancelListener(() -> { - if (mPendingImeControlRequest == request) { - abortPendingImeControlRequest(); - } - }); - } - 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, animationType); mRunningAnimations.add(new RunningAnimation(controller, animationType)); - if (cancellationSignal != null) { - cancellationSignal.setOnCancelListener(controller::onCancelled); - } + cancellationSignal.setOnCancelListener(controller::onCancelled); + return cancellationSignal; } /** @@ -884,8 +883,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // Show/hide animations always need to be relative to the display frame, in order that shown // and hidden state insets are correct. controlAnimationUnchecked( - types, new CancellationSignal(), listener, mState.getDisplayFrame(), fromIme, - listener.getDurationMs(), + types, listener, mState.getDisplayFrame(), fromIme, listener.getDurationMs(), INTERPOLATOR, true /* fade */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN); diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java index e8d9bb50c290..7f3641803770 100644 --- a/core/java/android/view/PendingInsetsController.java +++ b/core/java/android/view/PendingInsetsController.java @@ -16,8 +16,6 @@ package android.view; -import android.annotation.NonNull; -import android.annotation.Nullable; import android.os.CancellationSignal; import android.view.WindowInsets.Type.InsetsType; import android.view.animation.Interpolator; @@ -62,6 +60,21 @@ public class PendingInsetsController implements WindowInsetsController { } @Override + public CancellationSignal controlWindowInsetsAnimation(int types, long durationMillis, + Interpolator interpolator, + WindowInsetsAnimationControlListener listener) { + if (mReplayedInsetsController != null) { + return mReplayedInsetsController.controlWindowInsetsAnimation(types, durationMillis, + interpolator, listener); + } else { + listener.onCancelled(); + CancellationSignal cancellationSignal = new CancellationSignal(); + cancellationSignal.cancel(); + return cancellationSignal; + } + } + + @Override public void setSystemBarsAppearance(int appearance, int mask) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemBarsAppearance(appearance, mask); @@ -163,19 +176,6 @@ public class PendingInsetsController implements WindowInsetsController { mReplayedInsetsController = null; } - @Override - public void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, - @Nullable Interpolator interpolator, - CancellationSignal cancellationSignal, - @NonNull WindowInsetsAnimationControlListener listener) { - if (mReplayedInsetsController != null) { - mReplayedInsetsController.controlWindowInsetsAnimation(types, durationMillis, - interpolator, cancellationSignal, listener); - } else { - listener.onCancelled(); - } - } - private interface PendingRequest { void replay(InsetsController controller); } diff --git a/core/java/android/view/WindowInsetsAnimationControlListener.java b/core/java/android/view/WindowInsetsAnimationControlListener.java index faaf9203af32..701bd3158b1e 100644 --- a/core/java/android/view/WindowInsetsAnimationControlListener.java +++ b/core/java/android/view/WindowInsetsAnimationControlListener.java @@ -16,6 +16,7 @@ package android.view; +import android.annotation.Hide; import android.annotation.NonNull; import android.view.WindowInsets.Type.InsetsType; import android.view.inputmethod.EditorInfo; diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java index 0282ecac8920..2ad557e6d9f6 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -156,17 +156,16 @@ public interface WindowInsetsController { * calculate {@link WindowInsetsAnimation#getInterpolatedFraction()}. * @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the * windows are ready to be controlled, among other callbacks. - * @param cancellationSignal A cancellation signal that the caller can use to cancel the - * request to obtain control, or once they have control, to cancel the - * control. + * @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 WindowInsetsAnimation#getFraction() * @see WindowInsetsAnimation#getInterpolatedFraction() * @see WindowInsetsAnimation#getInterpolator() * @see WindowInsetsAnimation#getDurationMillis() */ - void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, + @NonNull + CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, @Nullable Interpolator interpolator, - @Nullable CancellationSignal cancellationSignal, @NonNull WindowInsetsAnimationControlListener listener); /** diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index e6634abfcb7f..023fc1736aca 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -56,12 +56,12 @@ import android.view.animation.LinearInterpolator; import android.view.test.InsetsModeSession; import android.widget.TextView; -import androidx.test.InstrumentationRegistry; -import androidx.test.runner.AndroidJUnit4; - import com.android.server.testutils.OffsettableClock; import com.android.server.testutils.TestHandler; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -72,6 +72,7 @@ import org.mockito.InOrder; import org.mockito.Mockito; import java.util.concurrent.CountDownLatch; +import java.util.function.Supplier; /** * Tests for {@link InsetsController}. @@ -203,7 +204,7 @@ public class InsetsControllerTest { WindowInsetsAnimationControlListener mockListener = mock(WindowInsetsAnimationControlListener.class); mController.controlWindowInsetsAnimation(statusBars(), 10 /* durationMs */, - new LinearInterpolator(), new CancellationSignal(), mockListener); + new LinearInterpolator(), mockListener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -223,7 +224,7 @@ public class InsetsControllerTest { WindowInsetsAnimationControlListener controlListener = mock(WindowInsetsAnimationControlListener.class); mController.controlWindowInsetsAnimation(0, 0 /* durationMs */, new LinearInterpolator(), - new CancellationSignal(), controlListener); + controlListener); mController.addOnControllableInsetsChangedListener( (controller, typeMask) -> assertEquals(0, typeMask)); verify(controlListener).onCancelled(); @@ -514,7 +515,7 @@ public class InsetsControllerTest { WindowInsetsAnimationControlListener mockListener = mock(WindowInsetsAnimationControlListener.class); mController.controlWindowInsetsAnimation(statusBars(), 0 /* durationMs */, - new LinearInterpolator(), new CancellationSignal(), mockListener); + new LinearInterpolator(), mockListener); ArgumentCaptor<WindowInsetsAnimationController> controllerCaptor = ArgumentCaptor.forClass(WindowInsetsAnimationController.class); @@ -541,10 +542,9 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener mockListener = mock(WindowInsetsAnimationControlListener.class); - CancellationSignal cancellationSignal = new CancellationSignal(); - mController.controlWindowInsetsAnimation( + CancellationSignal cancellationSignal = mController.controlWindowInsetsAnimation( statusBars(), 0 /* durationMs */, - new LinearInterpolator(), cancellationSignal, mockListener); + new LinearInterpolator(), mockListener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -567,8 +567,7 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), - null /* cancellationSignal */, listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -592,8 +591,7 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), - null /* cancellationSignal */, listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -613,8 +611,7 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), - null /* cancellationSignal */, listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -635,10 +632,8 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - CancellationSignal cancellationSignal = new CancellationSignal(); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), - cancellationSignal, listener); - cancellationSignal.cancel(); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener) + .cancel(); verify(listener).onCancelled(); diff --git a/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java b/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java index 33f859ef6663..9797178fca6e 100644 --- a/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java @@ -20,9 +20,8 @@ import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; - import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -36,12 +35,12 @@ import android.platform.test.annotations.Presubmit; import android.view.WindowInsetsController.OnControllableInsetsChangedListener; import android.view.animation.LinearInterpolator; -import androidx.test.runner.AndroidJUnit4; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import androidx.test.runner.AndroidJUnit4; + /** * Tests for {@link PendingInsetsControllerTest}. * @@ -96,11 +95,10 @@ public class PendingInsetsControllerTest { public void testControl() { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - CancellationSignal cancellationSignal = new CancellationSignal(); - mPendingInsetsController.controlWindowInsetsAnimation( - systemBars(), 0, new LinearInterpolator(), cancellationSignal, listener); + CancellationSignal signal = mPendingInsetsController.controlWindowInsetsAnimation( + systemBars(), 0, new LinearInterpolator(), listener); verify(listener).onCancelled(); - assertFalse(cancellationSignal.isCanceled()); + assertTrue(signal.isCanceled()); } @Test @@ -108,11 +106,10 @@ public class PendingInsetsControllerTest { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); mPendingInsetsController.replayAndAttach(mReplayedController); - CancellationSignal cancellationSignal = new CancellationSignal(); - mPendingInsetsController.controlWindowInsetsAnimation(systemBars(), 0L, - new LinearInterpolator(), cancellationSignal, listener); + mPendingInsetsController.controlWindowInsetsAnimation( + systemBars(), 0L, new LinearInterpolator(), listener); verify(mReplayedController).controlWindowInsetsAnimation(eq(systemBars()), eq(0L), any(), - eq(cancellationSignal), eq(listener)); + eq(listener)); } @Test diff --git a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java index f254e4d3267a..e41517085c36 100644 --- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java +++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java @@ -34,7 +34,9 @@ import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.view.Window; import android.view.WindowInsets; +import android.view.WindowInsets.Type; import android.view.WindowInsetsAnimation; import android.view.WindowInsetsAnimation.Callback; import android.view.WindowInsetsAnimationControlListener; @@ -99,7 +101,7 @@ public class WindowInsetsActivity extends AppCompatActivity { && !mRequestedController) { mRequestedController = true; v.getWindowInsetsController().controlWindowInsetsAnimation(ime(), - 1000, new LinearInterpolator(), null /* cancellationSignal */, + 1000, new LinearInterpolator(), mCurrentRequest = new WindowInsetsAnimationControlListener() { @Override public void onReady( @@ -206,7 +208,7 @@ public class WindowInsetsActivity extends AppCompatActivity { if ((types & ime()) != 0 && !hasControl) { hasControl = true; controller.controlWindowInsetsAnimation(ime(), -1, - new LinearInterpolator(), null /* cancellationSignal */, + new LinearInterpolator(), new WindowInsetsAnimationControlListener() { @Override public void onReady( |