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

Commit 41a66854 authored by Yifei Zhang's avatar Yifei Zhang Committed by Android (Google) Code Review
Browse files

Merge "swipe-dismiss: isolate animation definition" into main

parents 19f78acb 546e74d3
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -52,12 +52,13 @@ public class BackAnimationBackground {

    /**
     * Ensures the back animation background color layer is present.
     *
     * @param startRect The start bounds of the closing target.
     * @param color The background color.
     * @param transaction The animation transaction.
     */
    void ensureBackground(Rect startRect, int color,
            @NonNull SurfaceControl.Transaction transaction) {
    public void ensureBackground(
            Rect startRect, int color, @NonNull SurfaceControl.Transaction transaction) {
        if (mBackgroundSurface != null) {
            return;
        }
@@ -81,7 +82,12 @@ public class BackAnimationBackground {
        mIsRequestingStatusBarAppearance = false;
    }

    void removeBackground(@NonNull SurfaceControl.Transaction transaction) {
    /**
     * Remove the back animation background.
     *
     * @param transaction The animation transaction.
     */
    public void removeBackground(@NonNull SurfaceControl.Transaction transaction) {
        if (mBackgroundSurface == null) {
            return;
        }
@@ -93,11 +99,21 @@ public class BackAnimationBackground {
        mIsRequestingStatusBarAppearance = false;
    }

    /**
     * Attach a {@link StatusBarCustomizer} instance to allow status bar animate with back progress.
     *
     * @param customizer The {@link StatusBarCustomizer} to be used.
     */
    void setStatusBarCustomizer(StatusBarCustomizer customizer) {
        mCustomizer = customizer;
    }

    void onBackProgressed(float progress) {
    /**
     * Update back animation background with for the progress.
     *
     * @param progress Progress value from {@link android.window.BackProgressAnimator}
     */
    public void onBackProgressed(float progress) {
        if (mCustomizer == null || mStartBounds.isEmpty()) {
            return;
        }
+109 −130
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.content.ContentResolver;
@@ -43,7 +44,6 @@ import android.provider.Settings.Global;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.MathUtils;
import android.util.SparseArray;
import android.view.IRemoteAnimationRunner;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
@@ -70,6 +70,7 @@ import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;


import java.util.concurrent.atomic.AtomicBoolean;

/**
@@ -113,7 +114,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
    private boolean mShouldStartOnNextMoveEvent = false;
    /** @see #setTriggerBack(boolean) */
    private boolean mTriggerBack;
    private FlingAnimationUtils mFlingAnimationUtils;

    private final FlingAnimationUtils mFlingAnimationUtils;

    /** Registry for the back animations */
    private final ShellBackAnimationRegistry mShellBackAnimationRegistry;

    @Nullable
    private BackNavigationInfo mBackNavigationInfo;
@@ -135,13 +140,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont

    private final TouchTracker mTouchTracker = new TouchTracker();

    private final SparseArray<BackAnimationRunner> mAnimationDefinition = new SparseArray<>();
    @Nullable
    private IOnBackInvokedCallback mActiveCallback;

    private CrossActivityAnimation mDefaultActivityAnimation;
    private CustomizeActivityAnimation mCustomizeActivityAnimation;

    @VisibleForTesting
    final RemoteCallback mNavigationObserver = new RemoteCallback(
            new RemoteCallback.OnResultListener() {
@@ -169,10 +170,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
            @NonNull @ShellMainThread ShellExecutor shellExecutor,
            @NonNull @ShellBackgroundThread Handler backgroundHandler,
            Context context,
            @NonNull BackAnimationBackground backAnimationBackground) {
        this(shellInit, shellController, shellExecutor, backgroundHandler,
                ActivityTaskManager.getService(), context, context.getContentResolver(),
                backAnimationBackground);
            @NonNull BackAnimationBackground backAnimationBackground,
            ShellBackAnimationRegistry shellBackAnimationRegistry) {
        this(
                shellInit,
                shellController,
                shellExecutor,
                backgroundHandler,
                ActivityTaskManager.getService(),
                context,
                context.getContentResolver(),
                backAnimationBackground,
                shellBackAnimationRegistry);
    }

    @VisibleForTesting
@@ -182,8 +191,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
            @NonNull @ShellMainThread ShellExecutor shellExecutor,
            @NonNull @ShellBackgroundThread Handler bgHandler,
            @NonNull IActivityTaskManager activityTaskManager,
            Context context, ContentResolver contentResolver,
            @NonNull BackAnimationBackground backAnimationBackground) {
            Context context,
            ContentResolver contentResolver,
            @NonNull BackAnimationBackground backAnimationBackground,
            ShellBackAnimationRegistry shellBackAnimationRegistry) {
        mShellController = shellController;
        mShellExecutor = shellExecutor;
        mActivityTaskManager = activityTaskManager;
@@ -197,11 +208,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                .setMaxLengthSeconds(FLING_MAX_LENGTH_SECONDS)
                .setSpeedUpFactor(FLING_SPEED_UP_FACTOR)
                .build();
    }

    @VisibleForTesting
    void setEnableUAnimation(boolean enable) {
        IS_U_ANIMATION_ENABLED = enable;
        mShellBackAnimationRegistry = shellBackAnimationRegistry;
    }

    private void onInit() {
@@ -209,26 +216,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        createAdapter();
        mShellController.addExternalInterface(KEY_EXTRA_SHELL_BACK_ANIMATION,
                this::createExternalInterface, this);

        initBackAnimationRunners();
    }

    private void initBackAnimationRunners() {
        if (!IS_U_ANIMATION_ENABLED) {
            return;
        }

        final CrossTaskBackAnimation crossTaskAnimation =
                new CrossTaskBackAnimation(mContext, mAnimationBackground);
        mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_TASK,
                crossTaskAnimation.mBackAnimationRunner);
        mDefaultActivityAnimation =
                new CrossActivityAnimation(mContext, mAnimationBackground);
        mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                mDefaultActivityAnimation.mBackAnimationRunner);
        mCustomizeActivityAnimation =
                new CustomizeActivityAnimation(mContext, mAnimationBackground);
        // TODO (236760237): register dialog close animation when it's completed.
    }

    private void setupAnimationDeveloperSettingsObserver(
@@ -359,11 +346,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont

    void registerAnimation(@BackNavigationInfo.BackTargetType int type,
            @NonNull BackAnimationRunner runner) {
        mAnimationDefinition.set(type, runner);
        mShellBackAnimationRegistry.registerAnimation(type, runner);
    }

    void unregisterAnimation(@BackNavigationInfo.BackTargetType int type) {
        mAnimationDefinition.remove(type);
        mShellBackAnimationRegistry.unregisterAnimation(type);
    }

    /**
@@ -434,9 +421,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        final int backType = backNavigationInfo.getType();
        final boolean shouldDispatchToAnimator = shouldDispatchToAnimator();
        if (shouldDispatchToAnimator) {
            if (mAnimationDefinition.contains(backType)) {
                mAnimationDefinition.get(backType).startGesture();
            } else {
            if (!mShellBackAnimationRegistry.startGesture(backType)) {
                mActiveCallback = null;
            }
        } else {
@@ -459,6 +444,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        sendBackEvent(KeyEvent.ACTION_UP);
    }

    @SuppressLint("MissingPermission")
    private void sendBackEvent(int action) {
        final long when = SystemClock.uptimeMillis();
        final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK, 0 /* repeat */,
@@ -671,21 +657,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        }

        final int backType = mBackNavigationInfo.getType();
        final BackAnimationRunner runner = mAnimationDefinition.get(backType);
        // Simply trigger and finish back navigation when no animator defined.
        if (!shouldDispatchToAnimator() || runner == null) {
        if (!shouldDispatchToAnimator()
                || mShellBackAnimationRegistry.isAnimationCancelledOrNull(backType)) {
            invokeOrCancelBack();
            return;
        }
        if (runner.isWaitingAnimation()) {
        } else if (mShellBackAnimationRegistry.isWaitingAnimation(backType)) {
            ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready.");
            // Supposed it is in post commit animation state, and start the timeout to watch
            // if the animation is ready.
            mShellExecutor.executeDelayed(mAnimationTimeoutRunnable, MAX_ANIMATION_DURATION);
            return;
        } else if (runner.isAnimationCancelled()) {
            invokeOrCancelBack();
            return;
        }
        startPostCommitAnimation();
    }
@@ -737,12 +719,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        mShouldStartOnNextMoveEvent = false;
        mTouchTracker.reset();
        mActiveCallback = null;
        // reset to default
        if (mDefaultActivityAnimation != null
                && mAnimationDefinition.contains(BackNavigationInfo.TYPE_CROSS_ACTIVITY)) {
            mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                    mDefaultActivityAnimation.mBackAnimationRunner);
        }
        mShellBackAnimationRegistry.resetDefaultCrossActivity();
        if (mBackNavigationInfo != null) {
            mBackNavigationInfo.onBackNavigationFinished(mTriggerBack);
            mBackNavigationInfo = null;
@@ -750,43 +727,34 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        mTriggerBack = false;
    }

    private BackAnimationRunner getAnimationRunnerAndInit() {
        int type = mBackNavigationInfo.getType();
        // Initiate customized cross-activity animation, or fall back to cross activity animation
        if (type == BackNavigationInfo.TYPE_CROSS_ACTIVITY && mAnimationDefinition.contains(type)) {
            final BackNavigationInfo.CustomAnimationInfo animationInfo =
                    mBackNavigationInfo.getCustomAnimationInfo();
            if (animationInfo != null && mCustomizeActivityAnimation != null
                    && mCustomizeActivityAnimation.prepareNextAnimation(animationInfo)) {
                mAnimationDefinition.get(type).resetWaitingAnimation();
                mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                        mCustomizeActivityAnimation.mBackAnimationRunner);
            }
        }
        return mAnimationDefinition.get(type);
    }

    private void createAdapter() {
        IBackAnimationRunner runner = new IBackAnimationRunner.Stub() {
        IBackAnimationRunner runner =
                new IBackAnimationRunner.Stub() {
                    @Override
            public void onAnimationStart(RemoteAnimationTarget[] apps,
                    RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                    public void onAnimationStart(
                            RemoteAnimationTarget[] apps,
                            RemoteAnimationTarget[] wallpapers,
                            RemoteAnimationTarget[] nonApps,
                            IBackAnimationFinishedCallback finishedCallback) {
                mShellExecutor.execute(() -> {
                        mShellExecutor.execute(
                                () -> {
                                    if (mBackNavigationInfo == null) {
                                        Log.e(TAG, "Lack of navigation info to start animation.");
                                        return;
                                    }
                    final int type = mBackNavigationInfo.getType();
                    final BackAnimationRunner runner = getAnimationRunnerAndInit();
                                    final BackAnimationRunner runner =
                                            mShellBackAnimationRegistry.getAnimationRunnerAndInit(
                                                    mBackNavigationInfo);
                                    if (runner == null) {
                        Log.e(TAG, "Animation didn't be defined for type "
                                + BackNavigationInfo.typeToString(type));
                                        if (finishedCallback != null) {
                                            try {
                                                finishedCallback.onAnimationFinished(false);
                                            } catch (RemoteException e) {
                                Log.w(TAG, "Failed call IBackNaviAnimationController", e);
                                                Log.w(
                                                        TAG,
                                                        "Failed call IBackNaviAnimationController",
                                                        e);
                                            }
                                        }
                                        return;
@@ -794,22 +762,34 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                                    mActiveCallback = runner.getCallback();
                                    mBackAnimationFinishedCallback = finishedCallback;

                    ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()");
                    runner.startAnimation(apps, wallpapers, nonApps, () -> mShellExecutor.execute(
                            BackAnimationController.this::onBackAnimationFinished));
                                    ProtoLog.d(
                                            WM_SHELL_BACK_PREVIEW,
                                            "BackAnimationController: startAnimation()");
                                    runner.startAnimation(
                                            apps,
                                            wallpapers,
                                            nonApps,
                                            () ->
                                                    mShellExecutor.execute(
                                                            BackAnimationController.this
                                                                    ::onBackAnimationFinished));

                                    if (apps.length >= 1) {
                                        dispatchOnBackStarted(
                                mActiveCallback, mTouchTracker.createStartEvent(apps[0]));
                                                mActiveCallback,
                                                mTouchTracker.createStartEvent(apps[0]));
                                    }

                    // Dispatch the first progress after animation start for smoothing the initial
                    // animation, instead of waiting for next onMove.
                    final BackMotionEvent backFinish = mTouchTracker.createProgressEvent();
                                    // Dispatch the first progress after animation start for
                                    // smoothing the initial animation, instead of waiting for next
                                    // onMove.
                                    final BackMotionEvent backFinish =
                                            mTouchTracker.createProgressEvent();
                                    dispatchOnBackProgressed(mActiveCallback, backFinish);
                                    if (!mBackGestureStarted) {
                        // if the down -> up gesture happened before animation start, we have to
                        // trigger the uninterruptible transition to finish the back animation.
                                        // if the down -> up gesture happened before animation
                                        // start, we have to trigger the uninterruptible transition
                                        // to finish the back animation.
                                        startPostCommitAnimation();
                                    }
                                });
@@ -817,13 +797,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont

                    @Override
                    public void onAnimationCancelled() {
                mShellExecutor.execute(() -> {
                    final BackAnimationRunner runner = mAnimationDefinition.get(
                            mBackNavigationInfo.getType());
                    if (runner == null) {
                        mShellExecutor.execute(
                                () -> {
                                    if (!mShellBackAnimationRegistry.cancel(
                                            mBackNavigationInfo.getType())) {
                                        return;
                                    }
                    runner.cancelAnimation();
                                    if (!mBackGestureStarted) {
                                        invokeOrCancelBack();
                                    }
+3 −3
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import android.window.IOnBackInvokedCallback;
 * before it received IBackAnimationRunner#onAnimationStart, so the controller could continue
 * trigger the real back behavior.
 */
class BackAnimationRunner {
public class BackAnimationRunner {
    private static final String TAG = "ShellBackPreview";

    private final IOnBackInvokedCallback mCallback;
@@ -44,8 +44,8 @@ class BackAnimationRunner {
    /** True when the back animation is cancelled */
    private boolean mAnimationCancelled;

    BackAnimationRunner(@NonNull IOnBackInvokedCallback callback,
            @NonNull IRemoteAnimationRunner runner) {
    public BackAnimationRunner(
            @NonNull IOnBackInvokedCallback callback, @NonNull IRemoteAnimationRunner runner) {
        mCallback = callback;
        mRunner = runner;
    }
+11 −3
Original line number Diff line number Diff line
@@ -51,9 +51,11 @@ import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.annotations.ShellMainThread;

import javax.inject.Inject;

/** Class that defines cross-activity animation. */
@ShellMainThread
class CrossActivityAnimation {
public class CrossActivityAnimation extends ShellBackAnimation {
    /**
     * Minimum scale of the entering/closing window.
     */
@@ -106,6 +108,7 @@ class CrossActivityAnimation {
    private final SpringAnimation mLeavingProgressSpring;
    // Max window x-shift in pixels.
    private final float mWindowXShift;
    private final BackAnimationRunner mBackAnimationRunner;

    private float mEnteringProgress = 0f;
    private float mLeavingProgress = 0f;
@@ -126,11 +129,11 @@ class CrossActivityAnimation {
    private IRemoteAnimationFinishedCallback mFinishCallback;

    private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
    final BackAnimationRunner mBackAnimationRunner;

    private final BackAnimationBackground mBackground;

    CrossActivityAnimation(Context context, BackAnimationBackground background) {
    @Inject
    public CrossActivityAnimation(Context context, BackAnimationBackground background) {
        mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
        mBackAnimationRunner = new BackAnimationRunner(new Callback(), new Runner());
        mBackground = background;
@@ -357,6 +360,11 @@ class CrossActivityAnimation {
        mTransaction.apply();
    }

    @Override
    public BackAnimationRunner getRunner() {
        return mBackAnimationRunner;
    }

    private final class Callback extends IOnBackInvokedCallback.Default {
        @Override
        public void onBackStarted(BackMotionEvent backEvent) {
+37 −33
Original line number Diff line number Diff line
@@ -47,21 +47,23 @@ import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.annotations.ShellMainThread;

import javax.inject.Inject;

/**
 * Controls the animation of swiping back and returning to another task.
 *
 * This is a two part animation. The first part is an animation that tracks gesture location to
 * scale and move the closing and entering app windows.
 * Once the gesture is committed, the second part remains the closing window in place.
 * The entering window plays the rest of app opening transition to enter full screen.
 * <p>This is a two part animation. The first part is an animation that tracks gesture location to
 * scale and move the closing and entering app windows. Once the gesture is committed, the second
 * part remains the closing window in place. The entering window plays the rest of app opening
 * transition to enter full screen.
 *
 * This animation is used only for apps that enable back dispatching via
 * {@link android.window.OnBackInvokedDispatcher}. The controller registers
 * an {@link IOnBackInvokedCallback} with WM Shell and receives back dispatches when a back
 * navigation to launcher starts.
 * <p>This animation is used only for apps that enable back dispatching via {@link
 * android.window.OnBackInvokedDispatcher}. The controller registers an {@link
 * IOnBackInvokedCallback} with WM Shell and receives back dispatches when a back navigation to
 * launcher starts.
 */
@ShellMainThread
class CrossTaskBackAnimation {
public class CrossTaskBackAnimation extends ShellBackAnimation {
    private static final int BACKGROUNDCOLOR = 0x43433A;

    /**
@@ -104,28 +106,41 @@ class CrossTaskBackAnimation {

    private final float[] mTmpFloat9 = new float[9];
    private final float[] mTmpTranslate = {0, 0, 0};

    private final BackAnimationRunner mBackAnimationRunner;
    private final BackAnimationBackground mBackground;
    private RemoteAnimationTarget mEnteringTarget;
    private RemoteAnimationTarget mClosingTarget;
    private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();

    private boolean mBackInProgress = false;

    private boolean mIsRightEdge;
    private float mProgress = 0;
    private PointF mTouchPos = new PointF();
    private IRemoteAnimationFinishedCallback mFinishCallback;
    private BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
    final BackAnimationRunner mBackAnimationRunner;

    private final BackAnimationBackground mBackground;

    CrossTaskBackAnimation(Context context, BackAnimationBackground background) {
    @Inject
    public CrossTaskBackAnimation(Context context, BackAnimationBackground background) {
        mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
        mBackAnimationRunner = new BackAnimationRunner(new Callback(), new Runner());
        mBackground = background;
    }

    private static void computeScaleTransformMatrix(float scale, float[] matrix) {
        matrix[0] = scale;
        matrix[1] = 0;
        matrix[2] = 0;
        matrix[3] = 0;
        matrix[4] = scale;
        matrix[5] = 0;
        matrix[6] = 0;
        matrix[7] = 0;
        matrix[8] = scale;
    }

    private static float mapRange(float value, float min, float max) {
        return min + (value * (max - min));
    }

    private float getInterpolatedProgress(float backProgress) {
        return 1 - (1 - backProgress) * (1 - backProgress) * (1 - backProgress);
    }
@@ -233,18 +248,6 @@ class CrossTaskBackAnimation {
        mTransaction.setColorTransform(leash, mTmpFloat9, mTmpTranslate);
    }

    static void computeScaleTransformMatrix(float scale, float[] matrix) {
        matrix[0] = scale;
        matrix[1] = 0;
        matrix[2] = 0;
        matrix[3] = 0;
        matrix[4] = scale;
        matrix[5] = 0;
        matrix[6] = 0;
        matrix[7] = 0;
        matrix[8] = scale;
    }

    private void finishAnimation() {
        if (mEnteringTarget != null) {
            mEnteringTarget.leash.release();
@@ -314,8 +317,9 @@ class CrossTaskBackAnimation {
        valueAnimator.start();
    }

    private static float mapRange(float value, float min, float max) {
        return min + (value * (max - min));
    @Override
    public BackAnimationRunner getRunner() {
        return mBackAnimationRunner;
    }

    private final class Callback extends IOnBackInvokedCallback.Default {
@@ -340,7 +344,7 @@ class CrossTaskBackAnimation {
            mProgressAnimator.reset();
            onGestureCommitted();
        }
    };
    }

    private final class Runner extends IRemoteAnimationRunner.Default {
        @Override
@@ -360,5 +364,5 @@ class CrossTaskBackAnimation {
            startBackAnimation();
            mFinishCallback = finishedCallback;
        }
    };
    }
}
Loading