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

Commit 946871eb authored by wilsonshih's avatar wilsonshih
Browse files

Play seekable animation for customize activity transition API.

For cross-activity animation, support seekable animation if app
has customize activity exit transition by Window#setWindowAnimations or
android:windowAnimationStyle.
Because there could fall back to default cross-activity animation when
the customized animation was not able to load, defer assigning the
mActiveCallback when received onAnimationStart.

Bug: 259427810
Test: verify customized animation can play.
Test: atest BackNavigationControllerTests BackAnimationControllerTest\
CustomizeActivityAnimationTest

Change-Id: I59dc6ef75a226c634b06f483aeed7aec03087d18
parent 5a0ac4f8
Loading
Loading
Loading
Loading
+90 −2
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@ public final class BackNavigationInfo implements Parcelable {
    @Nullable
    private final IOnBackInvokedCallback mOnBackInvokedCallback;
    private final boolean mPrepareRemoteAnimation;
    @Nullable
    private final CustomAnimationInfo mCustomAnimationInfo;

    /**
     * Create a new {@link BackNavigationInfo} instance.
@@ -104,11 +106,13 @@ public final class BackNavigationInfo implements Parcelable {
    private BackNavigationInfo(@BackTargetType int type,
            @Nullable RemoteCallback onBackNavigationDone,
            @Nullable IOnBackInvokedCallback onBackInvokedCallback,
            boolean isPrepareRemoteAnimation) {
            boolean isPrepareRemoteAnimation,
            @Nullable CustomAnimationInfo customAnimationInfo) {
        mType = type;
        mOnBackNavigationDone = onBackNavigationDone;
        mOnBackInvokedCallback = onBackInvokedCallback;
        mPrepareRemoteAnimation = isPrepareRemoteAnimation;
        mCustomAnimationInfo = customAnimationInfo;
    }

    private BackNavigationInfo(@NonNull Parcel in) {
@@ -116,6 +120,7 @@ public final class BackNavigationInfo implements Parcelable {
        mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR);
        mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
        mPrepareRemoteAnimation = in.readBoolean();
        mCustomAnimationInfo = in.readTypedObject(CustomAnimationInfo.CREATOR);
    }

    /** @hide */
@@ -125,6 +130,7 @@ public final class BackNavigationInfo implements Parcelable {
        dest.writeTypedObject(mOnBackNavigationDone, flags);
        dest.writeStrongInterface(mOnBackInvokedCallback);
        dest.writeBoolean(mPrepareRemoteAnimation);
        dest.writeTypedObject(mCustomAnimationInfo, flags);
    }

    /**
@@ -172,6 +178,15 @@ public final class BackNavigationInfo implements Parcelable {
        }
    }

    /**
     * Get customize animation info.
     * @hide
     */
    @Nullable
    public CustomAnimationInfo getCustomAnimationInfo() {
        return mCustomAnimationInfo;
    }

    /** @hide */
    @Override
    public int describeContents() {
@@ -197,6 +212,7 @@ public final class BackNavigationInfo implements Parcelable {
                + "mType=" + typeToString(mType) + " (" + mType + ")"
                + ", mOnBackNavigationDone=" + mOnBackNavigationDone
                + ", mOnBackInvokedCallback=" + mOnBackInvokedCallback
                + ", mCustomizeAnimationInfo=" + mCustomAnimationInfo
                + '}';
    }

@@ -222,6 +238,67 @@ public final class BackNavigationInfo implements Parcelable {
        return String.valueOf(type);
    }

    /**
     * Information for customize back animation.
     * @hide
     */
    public static final class CustomAnimationInfo implements Parcelable {
        private final String mPackageName;
        private int mWindowAnimations;

        /**
         * The package name of the windowAnimations.
         */
        @NonNull
        public String getPackageName() {
            return mPackageName;
        }

        /**
         * The resource Id of window animations.
         */
        public int getWindowAnimations() {
            return mWindowAnimations;
        }

        public CustomAnimationInfo(@NonNull String packageName) {
            this.mPackageName = packageName;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            dest.writeString8(mPackageName);
            dest.writeInt(mWindowAnimations);
        }

        private CustomAnimationInfo(@NonNull Parcel in) {
            mPackageName = in.readString8();
            mWindowAnimations = in.readInt();
        }

        @Override
        public String toString() {
            return "CustomAnimationInfo, package name= " + mPackageName;
        }

        @NonNull
        public static final Creator<CustomAnimationInfo> CREATOR = new Creator<>() {
            @Override
            public CustomAnimationInfo createFromParcel(Parcel in) {
                return new CustomAnimationInfo(in);
            }

            @Override
            public CustomAnimationInfo[] newArray(int size) {
                return new CustomAnimationInfo[size];
            }
        };
    }
    /**
     * @hide
     */
@@ -233,6 +310,7 @@ public final class BackNavigationInfo implements Parcelable {
        @Nullable
        private IOnBackInvokedCallback mOnBackInvokedCallback = null;
        private boolean mPrepareRemoteAnimation;
        private CustomAnimationInfo mCustomAnimationInfo;

        /**
         * @see BackNavigationInfo#getType()
@@ -267,13 +345,23 @@ public final class BackNavigationInfo implements Parcelable {
            return this;
        }

        /**
         * Set windowAnimations for customize animation.
         */
        public Builder setWindowAnimations(String packageName, int windowAnimations) {
            mCustomAnimationInfo = new CustomAnimationInfo(packageName);
            mCustomAnimationInfo.mWindowAnimations = windowAnimations;
            return this;
        }

        /**
         * Builds and returns an instance of {@link BackNavigationInfo}
         */
        public BackNavigationInfo build() {
            return new BackNavigationInfo(mType, mOnBackNavigationDone,
                    mOnBackInvokedCallback,
                    mPrepareRemoteAnimation);
                    mPrepareRemoteAnimation,
                    mCustomAnimationInfo);
        }
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -37,14 +37,13 @@ oneway interface IBackAnimationRunner {

    /**
     * Called when the system is ready for the handler to start animating all the visible tasks.
     * @param type The back navigation type.
     * @param apps The list of departing (type=MODE_CLOSING) and entering (type=MODE_OPENING)
                   windows to animate,
     * @param wallpapers The list of wallpapers to animate.
     * @param nonApps The list of non-app windows such as Bubbles to animate.
     * @param finishedCallback The callback to invoke when the animation is finished.
     */
    void onAnimationStart(in int type,
    void onAnimationStart(
            in RemoteAnimationTarget[] apps,
            in RemoteAnimationTarget[] wallpapers,
            in RemoteAnimationTarget[] nonApps,
+28 −0
Original line number Diff line number Diff line
@@ -265,6 +265,34 @@ public class TransitionAnimation {
        }
        return null;
    }

    /** Get animation resId by attribute Id from specific LayoutParams */
    public int getAnimationResId(LayoutParams lp, int animAttr, int transit) {
        int resId = Resources.ID_NULL;
        if (animAttr >= 0) {
            AttributeCache.Entry ent = getCachedAnimations(lp);
            if (ent != null) {
                resId = ent.array.getResourceId(animAttr, 0);
            }
        }
        resId = updateToTranslucentAnimIfNeeded(resId, transit);
        return resId;
    }

    /** Get default animation resId */
    public int getDefaultAnimationResId(int animAttr, int transit) {
        int resId = Resources.ID_NULL;
        if (animAttr >= 0) {
            AttributeCache.Entry ent = getCachedAnimations(DEFAULT_PACKAGE,
                    mDefaultWindowAnimationStyleResId);
            if (ent != null) {
                resId = ent.array.getResourceId(animAttr, 0);
            }
        }
        resId = updateToTranslucentAnimIfNeeded(resId, transit);
        return resId;
    }

    /**
     * Load animation by attribute Id from a specific AnimationStyle resource.
     *
+43 −10
Original line number Diff line number Diff line
@@ -120,6 +120,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
    @Nullable
    private IOnBackInvokedCallback mActiveCallback;

    private CrossActivityAnimation mDefaultActivityAnimation;
    private CustomizeActivityAnimation mCustomizeActivityAnimation;

    @VisibleForTesting
    final RemoteCallback mNavigationObserver = new RemoteCallback(
            new RemoteCallback.OnResultListener() {
@@ -194,10 +197,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                new CrossTaskBackAnimation(mContext, mAnimationBackground);
        mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_TASK,
                crossTaskAnimation.mBackAnimationRunner);
        final CrossActivityAnimation crossActivityAnimation =
        mDefaultActivityAnimation =
                new CrossActivityAnimation(mContext, mAnimationBackground);
        mAnimationDefinition.set(BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                crossActivityAnimation.mBackAnimationRunner);
                mDefaultActivityAnimation.mBackAnimationRunner);
        mCustomizeActivityAnimation =
                new CustomizeActivityAnimation(mContext, mAnimationBackground);
        // TODO (236760237): register dialog close animation when it's completed.
    }

@@ -368,7 +373,6 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
        final boolean shouldDispatchToAnimator = shouldDispatchToAnimator();
        if (shouldDispatchToAnimator) {
            if (mAnimationDefinition.contains(backType)) {
                mActiveCallback = mAnimationDefinition.get(backType).getCallback();
                mAnimationDefinition.get(backType).startGesture();
            } else {
                mActiveCallback = null;
@@ -542,13 +546,12 @@ 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() || mActiveCallback == null) {
        if (!shouldDispatchToAnimator() || runner == null) {
            invokeOrCancelBack();
            return;
        }

        final BackAnimationRunner runner = mAnimationDefinition.get(backType);
        if (runner.isWaitingAnimation()) {
            ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Gesture released, but animation didn't ready.");
            return;
@@ -607,6 +610,12 @@ 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);
        }
        if (mBackNavigationInfo != null) {
            mBackNavigationInfo.onBackNavigationFinished(mTriggerBack);
            mBackNavigationInfo = null;
@@ -614,14 +623,35 @@ 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() {
            @Override
            public void onAnimationStart(int type, RemoteAnimationTarget[] apps,
            public void onAnimationStart(RemoteAnimationTarget[] apps,
                    RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                    IBackAnimationFinishedCallback finishedCallback) {
                mShellExecutor.execute(() -> {
                    final BackAnimationRunner runner = mAnimationDefinition.get(type);
                    if (mBackNavigationInfo == null) {
                        Log.e(TAG, "Lack of navigation info to start animation.");
                        return;
                    }
                    final int type = mBackNavigationInfo.getType();
                    final BackAnimationRunner runner = getAnimationRunnerAndInit();
                    if (runner == null) {
                        Log.e(TAG, "Animation didn't be defined for type "
                                + BackNavigationInfo.typeToString(type));
@@ -634,6 +664,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                        }
                        return;
                    }
                    mActiveCallback = runner.getCallback();
                    mBackAnimationFinishedCallback = finishedCallback;

                    ProtoLog.d(WM_SHELL_BACK_PREVIEW, "BackAnimationController: startAnimation()");
@@ -645,11 +676,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
                                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();
                    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.
                        final BackMotionEvent backFinish = mTouchTracker.createProgressEvent();
                        dispatchOnBackProgressed(mActiveCallback, backFinish);
                        startPostCommitAnimation();
                    }
                });
+4 −0
Original line number Diff line number Diff line
@@ -99,4 +99,8 @@ class BackAnimationRunner {
    boolean isAnimationCancelled() {
        return mAnimationCancelled;
    }

    void resetWaitingAnimation() {
        mWaitingAnimation = false;
    }
}
Loading