Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8d7ecdb authored by Adrian Roos's avatar Adrian Roos Committed by Android (Google) Code Review
Browse files

Merge "Insets Animation: Add CancellationSignal to controlWindowInsetsAnimation"

parents 524ec05b 3406fb97
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
+35 −15
Original line number Diff line number Diff line
@@ -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;
    }

    /**
+5 −2
Original line number Diff line number Diff line
@@ -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);

+51 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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();
@@ -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,