Loading api/current.txt +1 −1 Original line number Diff line number Diff line Loading @@ -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); core/java/android/view/InsetsController.java +35 −15 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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"; Loading Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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; } /** Loading core/java/android/view/WindowInsetsController.java +5 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading core/tests/coretests/src/android/view/InsetsControllerTest.java +51 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -515,6 +516,34 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @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(); Loading Loading @@ -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, Loading Loading
api/current.txt +1 −1 Original line number Diff line number Diff line Loading @@ -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);
core/java/android/view/InsetsController.java +35 −15 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading @@ -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"; Loading Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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; } /** Loading
core/java/android/view/WindowInsetsController.java +5 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading
core/tests/coretests/src/android/view/InsetsControllerTest.java +51 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -515,6 +516,34 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } @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(); Loading Loading @@ -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, Loading