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

Commit db5b0c23 authored by Adrian Roos's avatar Adrian Roos Committed by Jorim Jaggi
Browse files

WindowInsetsAnimation: Clean up API

Fixes issues the app developers have raised with
the WindowInsetsAnimation API:

- it really makes more sense to have the Animation
  as the outer class, and the Callback nested within
- it was not obvious previously that multiple animations
  could be running at the same time. A new argument to
  onProgress now makes this abundantly clear by passing
  in the list of running animations.
- The dispatch mode really fits better as a final
  property on the callback, rather than it being
  queried once from a getter.

Also fixes lint warnings.

Fixes: 143556682
Test: make checkapi; atest WindowInsetsControllerTests
Change-Id: I8cd8faac70dd5a15d779d2c983f0a0ea5d6bbd8e
parent e96570e2
Loading
Loading
Loading
Loading
+25 −24
Original line number Diff line number Diff line
@@ -53541,10 +53541,10 @@ package android.view {
    method public boolean dispatchUnhandledMove(android.view.View, int);
    method protected void dispatchVisibilityChanged(@NonNull android.view.View, int);
    method public void dispatchWindowFocusChanged(boolean);
    method public void dispatchWindowInsetsAnimationFinish(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation);
    method public void dispatchWindowInsetsAnimationPrepare(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation);
    method @NonNull public android.view.WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull android.view.WindowInsets);
    method @NonNull public android.view.WindowInsetsAnimationCallback.AnimationBounds dispatchWindowInsetsAnimationStart(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation, @NonNull android.view.WindowInsetsAnimationCallback.AnimationBounds);
    method public void dispatchWindowInsetsAnimationEnd(@NonNull android.view.WindowInsetsAnimation);
    method public void dispatchWindowInsetsAnimationPrepare(@NonNull android.view.WindowInsetsAnimation);
    method @NonNull public android.view.WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull android.view.WindowInsets, @NonNull java.util.List<android.view.WindowInsetsAnimation>);
    method @NonNull public android.view.WindowInsetsAnimation.Bounds dispatchWindowInsetsAnimationStart(@NonNull android.view.WindowInsetsAnimation, @NonNull android.view.WindowInsetsAnimation.Bounds);
    method @Deprecated public void dispatchWindowSystemUiVisiblityChanged(int);
    method public void dispatchWindowVisibilityChanged(int);
    method @CallSuper public void draw(android.graphics.Canvas);
@@ -54065,7 +54065,7 @@ package android.view {
    method public void setVisibility(int);
    method @Deprecated public void setWillNotCacheDrawing(boolean);
    method public void setWillNotDraw(boolean);
    method public void setWindowInsetsAnimationCallback(@Nullable android.view.WindowInsetsAnimationCallback);
    method public void setWindowInsetsAnimationCallback(@Nullable android.view.WindowInsetsAnimation.Callback);
    method public void setX(float);
    method public void setY(float);
    method public void setZ(float);
@@ -55232,25 +55232,8 @@ package android.view {
    method public static int tappableElement();
  }
  public interface WindowInsetsAnimationCallback {
    method public int getDispatchMode();
    method public default void onFinish(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation);
    method public default void onPrepare(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation);
    method @NonNull public android.view.WindowInsets onProgress(@NonNull android.view.WindowInsets);
    method @NonNull public default android.view.WindowInsetsAnimationCallback.AnimationBounds onStart(@NonNull android.view.WindowInsetsAnimationCallback.InsetsAnimation, @NonNull android.view.WindowInsetsAnimationCallback.AnimationBounds);
    field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1
    field public static final int DISPATCH_MODE_STOP = 0; // 0x0
  }
  public static final class WindowInsetsAnimationCallback.AnimationBounds {
    ctor public WindowInsetsAnimationCallback.AnimationBounds(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
    method @NonNull public android.graphics.Insets getLowerBound();
    method @NonNull public android.graphics.Insets getUpperBound();
    method @NonNull public android.view.WindowInsetsAnimationCallback.AnimationBounds inset(@NonNull android.graphics.Insets);
  }
  public static final class WindowInsetsAnimationCallback.InsetsAnimation {
    ctor public WindowInsetsAnimationCallback.InsetsAnimation(int, @Nullable android.view.animation.Interpolator, long);
  public final class WindowInsetsAnimation {
    ctor public WindowInsetsAnimation(int, @Nullable android.view.animation.Interpolator, long);
    method @FloatRange(from=0.0f, to=1.0f) public float getAlpha();
    method public long getDurationMillis();
    method @FloatRange(from=0.0f, to=1.0f) public float getFraction();
@@ -55261,6 +55244,24 @@ package android.view {
    method public void setFraction(@FloatRange(from=0.0f, to=1.0f) float);
  }
  public static final class WindowInsetsAnimation.Bounds {
    ctor public WindowInsetsAnimation.Bounds(@NonNull android.graphics.Insets, @NonNull android.graphics.Insets);
    method @NonNull public android.graphics.Insets getLowerBound();
    method @NonNull public android.graphics.Insets getUpperBound();
    method @NonNull public android.view.WindowInsetsAnimation.Bounds inset(@NonNull android.graphics.Insets);
  }
  public abstract static class WindowInsetsAnimation.Callback {
    ctor public WindowInsetsAnimation.Callback(int);
    method public final int getDispatchMode();
    method public void onEnd(@NonNull android.view.WindowInsetsAnimation);
    method public void onPrepare(@NonNull android.view.WindowInsetsAnimation);
    method @NonNull public abstract android.view.WindowInsets onProgress(@NonNull android.view.WindowInsets, @NonNull java.util.List<android.view.WindowInsetsAnimation>);
    method @NonNull public android.view.WindowInsetsAnimation.Bounds onStart(@NonNull android.view.WindowInsetsAnimation, @NonNull android.view.WindowInsetsAnimation.Bounds);
    field public static final int DISPATCH_MODE_CONTINUE_ON_SUBTREE = 1; // 0x1
    field public static final int DISPATCH_MODE_STOP = 0; // 0x0
  }
  public interface WindowInsetsAnimationControlListener {
    method public void onCancelled();
    method public void onReady(@NonNull android.view.WindowInsetsAnimationController, int);
+6 −6
Original line number Diff line number Diff line
@@ -17,8 +17,7 @@
package android.view;

import android.view.InsetsController.LayoutInsetsDuringAnimation;
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds;

/**
 * Provide an interface to let InsetsAnimationControlImpl call back into its owner.
@@ -29,15 +28,16 @@ public interface InsetsAnimationControlCallbacks {
    /**
     * Executes the necessary code to start the animation in the correct order, including:
     * <ul>
     *     <li>Dispatch {@link WindowInsetsAnimationCallback#onPrepare}</li>
     *     <li>Dispatch {@link WindowInsetsAnimation.Callback#onPrepare}</li>
     *     <li>Update insets state and run layout according to {@code layoutDuringAnimation}</li>
     *     <li>Dispatch {@link WindowInsetsAnimationCallback#onStart}</li>
     *     <li>Dispatch {@link WindowInsetsAnimation.Callback#onStart}</li>
     *     <li>Dispatch {@link WindowInsetsAnimationControlListener#onReady}</li>
     * </ul>
     */
    void startAnimation(InsetsAnimationControlImpl controller,
            WindowInsetsAnimationControlListener listener, int types, InsetsAnimation animation,
            AnimationBounds bounds, @LayoutInsetsDuringAnimation int layoutDuringAnimation);
            WindowInsetsAnimationControlListener listener, int types,
            WindowInsetsAnimation animation,
            Bounds bounds, @LayoutInsetsDuringAnimation int layoutDuringAnimation);

    /**
     * Schedule the apply by posting the animation callback.
+5 −6
Original line number Diff line number Diff line
@@ -35,8 +35,7 @@ import android.view.InsetsState.InternalInsetsSide;
import android.view.InsetsState.InternalInsetsType;
import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Interpolator;

@@ -67,7 +66,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
    private final InsetsState mInitialInsetsState;
    private final @InsetsType int mTypes;
    private final InsetsAnimationControlCallbacks mController;
    private final WindowInsetsAnimationCallback.InsetsAnimation mAnimation;
    private final WindowInsetsAnimation mAnimation;
    private final Rect mFrame;
    private final boolean mFade;
    private Insets mCurrentInsets;
@@ -100,11 +99,11 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
        mFrame = new Rect(frame);
        buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls);

        mAnimation = new WindowInsetsAnimationCallback.InsetsAnimation(mTypes, interpolator,
        mAnimation = new WindowInsetsAnimation(mTypes, interpolator,
                durationMs);
        mAnimation.setAlpha(getCurrentAlpha());
        mController.startAnimation(this, listener, types, mAnimation,
                new AnimationBounds(mHiddenInsets, mShownInsets), layoutInsetsDuringAnimation);
                new Bounds(mHiddenInsets, mShownInsets), layoutInsetsDuringAnimation);
    }

    @Override
@@ -212,7 +211,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
        return mCancelled;
    }

    InsetsAnimation getAnimation() {
    WindowInsetsAnimation getAnimation() {
        return mAnimation;
    }

+15 −8
Original line number Diff line number Diff line
@@ -46,8 +46,7 @@ import android.view.SurfaceControl.Transaction;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
@@ -58,6 +57,8 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;

/**
@@ -275,6 +276,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation

    private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
    private final ArrayList<RunningAnimation> mRunningAnimations = new ArrayList<>();
    private final ArrayList<WindowInsetsAnimation> mRunningInsetsAnimations = new ArrayList<>();
    private final List<WindowInsetsAnimation> mUnmodifiableRunningInsetsAnimations =
            Collections.unmodifiableList(mRunningInsetsAnimations);
    private final ArrayList<InsetsAnimationControlImpl> mTmpFinishedControls = new ArrayList<>();
    private WindowInsets mLastInsets;

@@ -337,10 +341,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                    mLastInsets.shouldAlwaysConsumeSystemBars(), mLastInsets.getDisplayCutout(),
                    mLastLegacyContentInsets, mLastLegacyStableInsets, mLastLegacySoftInputMode,
                    mLastLegacySystemUiFlags, null /* typeSideMap */);
            mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets);
            mViewRoot.mView.dispatchWindowInsetsAnimationProgress(insets,
                    mUnmodifiableRunningInsetsAnimations);

            for (int i = mTmpFinishedControls.size() - 1; i >= 0; i--) {
                dispatchAnimationFinished(mTmpFinishedControls.get(i).getAnimation());
                dispatchAnimationEnd(mTmpFinishedControls.get(i).getAnimation());
            }
        };
    }
@@ -579,6 +584,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                frame, mState, listener, typesReady, this, durationMs, interpolator, fade,
                layoutInsetsDuringAnimation);
        mRunningAnimations.add(new RunningAnimation(controller, animationType));
        mRunningInsetsAnimations.add(controller.getAnimation());
        cancellationSignal.setOnCancelListener(controller::onCancelled);
        return cancellationSignal;
    }
@@ -729,6 +735,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
            if (mRunningAnimations.get(i).control == control) {
                mRunningAnimations.remove(i);
                mRunningInsetsAnimations.remove(i);
                break;
            }
        }
@@ -875,8 +882,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    @VisibleForTesting
    @Override
    public void startAnimation(InsetsAnimationControlImpl controller,
            WindowInsetsAnimationControlListener listener, int types, InsetsAnimation animation,
            AnimationBounds bounds, int layoutDuringAnimation) {
            WindowInsetsAnimationControlListener listener, int types,
            WindowInsetsAnimation animation, Bounds bounds, int layoutDuringAnimation) {
        if (layoutDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
            showDirectly(types);
        } else {
@@ -904,8 +911,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    }

    @VisibleForTesting
    public void dispatchAnimationFinished(InsetsAnimation animation) {
        mViewRoot.mView.dispatchWindowInsetsAnimationFinish(animation);
    public void dispatchAnimationEnd(WindowInsetsAnimation animation) {
        mViewRoot.mView.dispatchWindowInsetsAnimationEnd(animation);
    }

    @VisibleForTesting
+30 −26
Original line number Diff line number Diff line
@@ -112,8 +112,7 @@ import android.view.AccessibilityIterators.WordTextSegmentIterator;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Window.OnContentApplyWindowInsetsListener;
import android.view.WindowInsets.Type;
import android.view.WindowInsetsAnimationCallback.AnimationBounds;
import android.view.WindowInsetsAnimationCallback.InsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
@@ -4672,7 +4671,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
        WindowInsetsAnimationCallback mWindowInsetsAnimationCallback;
        WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback;
        /**
         * This lives here since it's only valid for interactive views.
@@ -11200,43 +11199,45 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    /**
     * Sets a {@link WindowInsetsAnimationCallback} to be notified about animations of windows that
     * Sets a {@link WindowInsetsAnimation.Callback} to be notified about animations of windows that
     * cause insets.
     * <p>
     * When setting a listener, it's {@link WindowInsetsAnimationCallback#getDispatchMode() dispatch
     * mode} will be retrieved and recorded until another listener will be set.
     * The callback's {@link WindowInsetsAnimation.Callback#getDispatchMode()
     * dispatch mode} will affect whether animation callbacks are dispatched to the children of
     * this view.
     * </p>
     * @param listener The listener to set.
     * @param callback The callback to set.
     */
    public void setWindowInsetsAnimationCallback(@Nullable WindowInsetsAnimationCallback listener) {
        getListenerInfo().mWindowInsetsAnimationCallback = listener;
    public void setWindowInsetsAnimationCallback(
            @Nullable WindowInsetsAnimation.Callback callback) {
        getListenerInfo().mWindowInsetsAnimationCallback = callback;
    }
    /**
     * Dispatches {@link WindowInsetsAnimationCallback#onPrepare(InsetsAnimation)}
     * Dispatches {@link WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)}
     * when Window Insets animation is being prepared.
     * @param animation current animation
     *
     * @see WindowInsetsAnimationCallback#onPrepare(InsetsAnimation)
     * @see WindowInsetsAnimation.Callback#onPrepare(WindowInsetsAnimation)
     */
    public void dispatchWindowInsetsAnimationPrepare(
            @NonNull InsetsAnimation animation) {
            @NonNull WindowInsetsAnimation animation) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            mListenerInfo.mWindowInsetsAnimationCallback.onPrepare(animation);
        }
    }
    /**
     * Dispatches {@link WindowInsetsAnimationCallback#onStart(InsetsAnimation, AnimationBounds)}
     * Dispatches {@link WindowInsetsAnimation.Callback#onStart(WindowInsetsAnimation, Bounds)}
     * when Window Insets animation is started.
     * @param animation current animation
     * @param bounds the upper and lower {@link AnimationBounds} that provides range of
     *  {@link InsetsAnimation}.
     * @return the upper and lower {@link AnimationBounds}.
     * @param bounds the upper and lower {@link Bounds} that provides range of
     *  {@link WindowInsetsAnimation}.
     * @return the upper and lower {@link Bounds}.
     */
    @NonNull
    public AnimationBounds dispatchWindowInsetsAnimationStart(
            @NonNull InsetsAnimation animation, @NonNull AnimationBounds bounds) {
    public Bounds dispatchWindowInsetsAnimationStart(
            @NonNull WindowInsetsAnimation animation, @NonNull Bounds bounds) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            return mListenerInfo.mWindowInsetsAnimationCallback.onStart(animation, bounds);
        }
@@ -11244,28 +11245,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    /**
     * Dispatches {@link WindowInsetsAnimationCallback#onProgress(WindowInsets)}
     * Dispatches {@link WindowInsetsAnimation.Callback#onProgress(WindowInsets, List)}
     * when Window Insets animation makes progress.
     * @param insets The current {@link WindowInsets}.
     * @param runningAnimations The currently running {@link WindowInsetsAnimation}s.
     * @return current {@link WindowInsets}.
     */
    @NonNull
    public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets) {
    public WindowInsets dispatchWindowInsetsAnimationProgress(@NonNull WindowInsets insets,
            @NonNull List<WindowInsetsAnimation> runningAnimations) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets);
            return mListenerInfo.mWindowInsetsAnimationCallback.onProgress(insets,
                    runningAnimations);
        } else {
            return insets;
        }
    }
    /**
     * Dispatches {@link WindowInsetsAnimationCallback#onFinish(InsetsAnimation)}
     * when Window Insets animation finishes.
     * @param animation The current ongoing {@link InsetsAnimation}.
     * Dispatches {@link WindowInsetsAnimation.Callback#onEnd(WindowInsetsAnimation)}
     * when Window Insets animation ends.
     * @param animation The current ongoing {@link WindowInsetsAnimation}.
     */
    public void dispatchWindowInsetsAnimationFinish(@NonNull InsetsAnimation animation) {
    public void dispatchWindowInsetsAnimationEnd(@NonNull WindowInsetsAnimation animation) {
        if (mListenerInfo != null && mListenerInfo.mWindowInsetsAnimationCallback != null) {
            mListenerInfo.mWindowInsetsAnimationCallback.onFinish(animation);
            mListenerInfo.mWindowInsetsAnimationCallback.onEnd(animation);
        }
    }
Loading