diff --git a/api/current.txt b/api/current.txt index 2f6870c96907d..3d722c89605fe 100644 --- a/api/current.txt +++ b/api/current.txt @@ -55589,7 +55589,7 @@ package android.view { public interface WindowInsetsController { method public void addOnControllableInsetsChangedListener(@NonNull android.view.WindowInsetsController.OnControllableInsetsChangedListener); - method @NonNull public android.os.CancellationSignal controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @NonNull android.view.WindowInsetsAnimationControlListener); + method public void controlWindowInsetsAnimation(int, long, @Nullable android.view.animation.Interpolator, @Nullable android.os.CancellationSignal, @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 88e7f2ed9cf1f..123b9db75804f 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -53,7 +53,6 @@ import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import java.io.PrintWriter; @@ -518,14 +517,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation PendingControlRequest pendingRequest = mPendingImeControlRequest; mPendingImeControlRequest = null; mHandler.removeCallbacks(mPendingControlTimeout); - CancellationSignal cancellationSignal = controlAnimationUnchecked( - pendingRequest.types, + controlAnimationUnchecked( + pendingRequest.types, pendingRequest.cancellationSignal, pendingRequest.listener, mFrame, true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator, false /* fade */, pendingRequest.animationType, pendingRequest.layoutInsetsDuringAnimation, pendingRequest.useInsetsAnimationThread); - pendingRequest.cancellationSignal.setOnCancelListener(cancellationSignal::cancel); return; } @@ -571,24 +569,26 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } @Override - public CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, long durationMs, + public void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, @Nullable Interpolator interpolator, + @Nullable CancellationSignal cancellationSignal, @NonNull WindowInsetsAnimationControlListener listener) { - return controlWindowInsetsAnimation(types, listener, false /* fromIme */, durationMs, - interpolator, ANIMATION_TYPE_USER); + controlWindowInsetsAnimation(types, cancellationSignal, listener, + false /* fromIme */, durationMillis, interpolator, ANIMATION_TYPE_USER); } - private CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, - WindowInsetsAnimationControlListener listener, boolean fromIme, long durationMs, - @Nullable Interpolator interpolator, @AnimationType int animationType) { + private void controlWindowInsetsAnimation(@InsetsType int types, + @Nullable CancellationSignal cancellationSignal, + WindowInsetsAnimationControlListener listener, + boolean fromIme, long durationMs, @Nullable Interpolator interpolator, + @AnimationType int animationType) { if (!checkDisplayFramesForControlling()) { listener.onCancelled(); - CancellationSignal cancellationSignal = new CancellationSignal(); - cancellationSignal.cancel(); - return cancellationSignal; + return; } - return controlAnimationUnchecked(types, listener, mFrame, fromIme, durationMs, interpolator, - false /* fade */, animationType, getLayoutInsetsDuringAnimationMode(types), + controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs, + interpolator, false /* fade */, animationType, + getLayoutInsetsDuringAnimationMode(types), false /* useInsetsAnimationThread */); } @@ -599,18 +599,17 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return mState.getDisplayFrame().equals(mFrame); } - private CancellationSignal controlAnimationUnchecked(@InsetsType int types, + private void controlAnimationUnchecked(@InsetsType int types, + @Nullable CancellationSignal cancellationSignal, WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme, long durationMs, Interpolator interpolator, boolean fade, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread) { - CancellationSignal cancellationSignal = new CancellationSignal(); if (types == 0) { // nothing to animate. listener.onCancelled(); - cancellationSignal.cancel(); - return cancellationSignal; + return; } cancelExistingControllers(types); mLastStartedAnimTypes |= types; @@ -631,18 +630,19 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation useInsetsAnimationThread); mPendingImeControlRequest = request; mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS); - cancellationSignal.setOnCancelListener(() -> { - if (mPendingImeControlRequest == request) { - abortPendingImeControlRequest(); - } - }); - return cancellationSignal; + if (cancellationSignal != null) { + cancellationSignal.setOnCancelListener(() -> { + if (mPendingImeControlRequest == request) { + abortPendingImeControlRequest(); + } + }); + } + return; } if (typesReady == 0) { listener.onCancelled(); - cancellationSignal.cancel(); - return cancellationSignal; + return; } @@ -654,13 +654,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation frame, mState, listener, typesReady, this, durationMs, interpolator, fade, animationType); mRunningAnimations.add(new RunningAnimation(runner, animationType)); - cancellationSignal.setOnCancelListener(runner::cancel); + if (cancellationSignal != null) { + cancellationSignal.setOnCancelListener(runner::cancel); + } if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) { showDirectly(types); } else { hideDirectly(types, false /* animationFinished */, animationType); } - return cancellationSignal; } /** @@ -922,7 +923,8 @@ 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, listener, mState.getDisplayFrame(), fromIme, listener.getDurationMs(), + types, null /* cancellationSignal */, 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 7f3641803770d..e8d9bb50c2905 100644 --- a/core/java/android/view/PendingInsetsController.java +++ b/core/java/android/view/PendingInsetsController.java @@ -16,6 +16,8 @@ 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; @@ -59,21 +61,6 @@ 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) { @@ -176,6 +163,19 @@ 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 701bd3158b1e0..faaf9203af325 100644 --- a/core/java/android/view/WindowInsetsAnimationControlListener.java +++ b/core/java/android/view/WindowInsetsAnimationControlListener.java @@ -16,7 +16,6 @@ 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 2ad557e6d9f64..0282ecac8920d 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -156,16 +156,17 @@ 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. - * @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. + * @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. * @see WindowInsetsAnimation#getFraction() * @see WindowInsetsAnimation#getInterpolatedFraction() * @see WindowInsetsAnimation#getInterpolator() * @see WindowInsetsAnimation#getDurationMillis() */ - @NonNull - CancellationSignal controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, + void 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 f1ab8ddebce62..42ab2e7916415 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -58,12 +58,12 @@ import android.view.animation.LinearInterpolator; import android.view.test.InsetsModeSession; import android.widget.TextView; -import com.android.server.testutils.OffsettableClock; -import com.android.server.testutils.TestHandler; - import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.server.testutils.OffsettableClock; +import com.android.server.testutils.TestHandler; + import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -74,7 +74,6 @@ import org.mockito.InOrder; import org.mockito.Mockito; import java.util.concurrent.CountDownLatch; -import java.util.function.Supplier; /** * Tests for {@link InsetsController}. @@ -199,7 +198,7 @@ public class InsetsControllerTest { WindowInsetsAnimationControlListener mockListener = mock(WindowInsetsAnimationControlListener.class); mController.controlWindowInsetsAnimation(statusBars(), 10 /* durationMs */, - new LinearInterpolator(), mockListener); + new LinearInterpolator(), new CancellationSignal(), mockListener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -219,7 +218,7 @@ public class InsetsControllerTest { WindowInsetsAnimationControlListener controlListener = mock(WindowInsetsAnimationControlListener.class); mController.controlWindowInsetsAnimation(0, 0 /* durationMs */, new LinearInterpolator(), - controlListener); + new CancellationSignal(), controlListener); mController.addOnControllableInsetsChangedListener( (controller, typeMask) -> assertEquals(0, typeMask)); verify(controlListener).onCancelled(); @@ -498,7 +497,7 @@ public class InsetsControllerTest { WindowInsetsAnimationControlListener mockListener = mock(WindowInsetsAnimationControlListener.class); mController.controlWindowInsetsAnimation(statusBars(), 0 /* durationMs */, - new LinearInterpolator(), mockListener); + new LinearInterpolator(), new CancellationSignal(), mockListener); ArgumentCaptor controllerCaptor = ArgumentCaptor.forClass(WindowInsetsAnimationController.class); @@ -523,9 +522,10 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener mockListener = mock(WindowInsetsAnimationControlListener.class); - CancellationSignal cancellationSignal = mController.controlWindowInsetsAnimation( + CancellationSignal cancellationSignal = new CancellationSignal(); + mController.controlWindowInsetsAnimation( statusBars(), 0 /* durationMs */, - new LinearInterpolator(), mockListener); + new LinearInterpolator(), cancellationSignal, mockListener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -548,7 +548,8 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), + null /* cancellationSignal */, listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -572,7 +573,8 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), + null /* cancellationSignal */, listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -592,7 +594,8 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), + null /* cancellationSignal */, listener); // Ready gets deferred until next predraw mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw(); @@ -613,8 +616,10 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), listener) - .cancel(); + CancellationSignal cancellationSignal = new CancellationSignal(); + mController.controlWindowInsetsAnimation(ime(), 0, new LinearInterpolator(), + cancellationSignal, listener); + cancellationSignal.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 9797178fca6e2..33f859ef6663a 100644 --- a/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/PendingInsetsControllerTest.java @@ -20,8 +20,9 @@ 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.assertTrue; +import static org.junit.Assert.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -35,12 +36,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}. * @@ -95,10 +96,11 @@ public class PendingInsetsControllerTest { public void testControl() { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); - CancellationSignal signal = mPendingInsetsController.controlWindowInsetsAnimation( - systemBars(), 0, new LinearInterpolator(), listener); + CancellationSignal cancellationSignal = new CancellationSignal(); + mPendingInsetsController.controlWindowInsetsAnimation( + systemBars(), 0, new LinearInterpolator(), cancellationSignal, listener); verify(listener).onCancelled(); - assertTrue(signal.isCanceled()); + assertFalse(cancellationSignal.isCanceled()); } @Test @@ -106,10 +108,11 @@ public class PendingInsetsControllerTest { WindowInsetsAnimationControlListener listener = mock(WindowInsetsAnimationControlListener.class); mPendingInsetsController.replayAndAttach(mReplayedController); - mPendingInsetsController.controlWindowInsetsAnimation( - systemBars(), 0L, new LinearInterpolator(), listener); + CancellationSignal cancellationSignal = new CancellationSignal(); + mPendingInsetsController.controlWindowInsetsAnimation(systemBars(), 0L, + new LinearInterpolator(), cancellationSignal, listener); verify(mReplayedController).controlWindowInsetsAnimation(eq(systemBars()), eq(0L), any(), - eq(listener)); + eq(cancellationSignal), 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 e41517085c36d..f254e4d3267ab 100644 --- a/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java +++ b/tests/WindowInsetsTests/src/com/google/android/test/windowinsetstests/WindowInsetsActivity.java @@ -34,9 +34,7 @@ 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; @@ -101,7 +99,7 @@ public class WindowInsetsActivity extends AppCompatActivity { && !mRequestedController) { mRequestedController = true; v.getWindowInsetsController().controlWindowInsetsAnimation(ime(), - 1000, new LinearInterpolator(), + 1000, new LinearInterpolator(), null /* cancellationSignal */, mCurrentRequest = new WindowInsetsAnimationControlListener() { @Override public void onReady( @@ -208,7 +206,7 @@ public class WindowInsetsActivity extends AppCompatActivity { if ((types & ime()) != 0 && !hasControl) { hasControl = true; controller.controlWindowInsetsAnimation(ime(), -1, - new LinearInterpolator(), + new LinearInterpolator(), null /* cancellationSignal */, new WindowInsetsAnimationControlListener() { @Override public void onReady(