diff --git a/api/current.txt b/api/current.txt index 6632546bf99d7..4e203dd7c0f71 100644 --- a/api/current.txt +++ b/api/current.txt @@ -55580,7 +55580,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 607886f3b13bb..b1da4cc60ad16 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -52,7 +52,6 @@ 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; @@ -494,13 +493,12 @@ 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.cancellationSignal.setOnCancelListener(cancellationSignal::cancel); return; } @@ -546,24 +544,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)); } private boolean checkDisplayFramesForControlling() { @@ -573,17 +573,16 @@ 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) { - CancellationSignal cancellationSignal = new CancellationSignal(); if (types == 0) { // nothing to animate. listener.onCancelled(); - cancellationSignal.cancel(); - return cancellationSignal; + return; } cancelExistingControllers(types); mLastStartedAnimTypes |= types; @@ -603,26 +602,28 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation interpolator, animationType, layoutInsetsDuringAnimation, cancellationSignal); 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; } final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(controls, frame, mState, listener, typesReady, this, durationMs, interpolator, fade, layoutInsetsDuringAnimation, animationType); mRunningAnimations.add(new RunningAnimation(controller, animationType)); - cancellationSignal.setOnCancelListener(controller::onCancelled); - return cancellationSignal; + if (cancellationSignal != null) { + cancellationSignal.setOnCancelListener(controller::onCancelled); + } } /** @@ -883,7 +884,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, new 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 023fc1736acaf..e6634abfcb7fd 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 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; @@ -72,7 +72,6 @@ import org.mockito.InOrder; import org.mockito.Mockito; import java.util.concurrent.CountDownLatch; -import java.util.function.Supplier; /** * Tests for {@link InsetsController}. @@ -204,7 +203,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(); @@ -224,7 +223,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(); @@ -515,7 +514,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); @@ -542,9 +541,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(); @@ -567,7 +567,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(); @@ -591,7 +592,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(); @@ -611,7 +613,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(); @@ -632,8 +635,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(