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

Commit 47e45086 authored by omarmt's avatar omarmt Committed by Omar Miatello
Browse files

Add isAnimationCallback() in BackNavigationInfo

This method returns if the callback is an OnBackAnimationCallback.
This value can be serialized and can be used to determine whether or not to run predictive animations when you have no way to check the callback directly, for example in the BackAnimationController you only have access to the IOnBackInvokedCallback.

Why?
OnBackAnimationCallback is used by apps that want to play a custom animation when the user swipes back.
OnBackAnimationCallback exposes BackEvent every time there is a new progress value.

Ideally, we would like to expose the velocity only on the last progress value (or onBackInvoked()), but to do that we have to change the API. We are unable to do so now.

Therefore, we decided to handle the fling gesture in the system instead. As a result, we now need to determine if the app supports OnBackAnimationCallback so that we only send the fling if we have an OnBackAnimationCallback registered.

BackAnimationController can now produce more back events. This is done by producing more events when the user lifts their finger. This way, the developer does not have to handle the fling gesture. This approach was chosen because the velocity cannot be exposed in the BackEvent.

Test: atest BackNavigationControllerTests
Bug: 263402927
Change-Id: I4d85253c9ade39f35ef0d8c70c6b1c7c31b1390d
parent 2c574049
Loading
Loading
Loading
Loading
+31 −5
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ public final class BackNavigationInfo implements Parcelable {
    @Nullable
    private final IOnBackInvokedCallback mOnBackInvokedCallback;
    private final boolean mPrepareRemoteAnimation;
    private final boolean mAnimationCallback;
    @Nullable
    private final CustomAnimationInfo mCustomAnimationInfo;

@@ -109,11 +110,13 @@ public final class BackNavigationInfo implements Parcelable {
            @Nullable RemoteCallback onBackNavigationDone,
            @Nullable IOnBackInvokedCallback onBackInvokedCallback,
            boolean isPrepareRemoteAnimation,
            boolean isAnimationCallback,
            @Nullable CustomAnimationInfo customAnimationInfo) {
        mType = type;
        mOnBackNavigationDone = onBackNavigationDone;
        mOnBackInvokedCallback = onBackInvokedCallback;
        mPrepareRemoteAnimation = isPrepareRemoteAnimation;
        mAnimationCallback = isAnimationCallback;
        mCustomAnimationInfo = customAnimationInfo;
    }

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

@@ -132,6 +136,7 @@ public final class BackNavigationInfo implements Parcelable {
        dest.writeTypedObject(mOnBackNavigationDone, flags);
        dest.writeStrongInterface(mOnBackInvokedCallback);
        dest.writeBoolean(mPrepareRemoteAnimation);
        dest.writeBoolean(mAnimationCallback);
        dest.writeTypedObject(mCustomAnimationInfo, flags);
    }

@@ -159,13 +164,21 @@ public final class BackNavigationInfo implements Parcelable {
    }

    /**
     * Return true if the core is preparing a back gesture nimation.
     * Return true if the core is preparing a back gesture animation.
     * @hide
     */
    public boolean isPrepareRemoteAnimation() {
        return mPrepareRemoteAnimation;
    }

    /**
     * Return true if the callback is {@link OnBackAnimationCallback}.
     * @hide
     */
    public boolean isAnimationCallback() {
        return mAnimationCallback;
    }

    /**
     * Callback to be called when the back preview is finished in order to notify the server that
     * it can clean up the resources created for the animation.
@@ -214,6 +227,8 @@ public final class BackNavigationInfo implements Parcelable {
                + "mType=" + typeToString(mType) + " (" + mType + ")"
                + ", mOnBackNavigationDone=" + mOnBackNavigationDone
                + ", mOnBackInvokedCallback=" + mOnBackInvokedCallback
                + ", mPrepareRemoteAnimation=" + mPrepareRemoteAnimation
                + ", mAnimationCallback=" + mAnimationCallback
                + ", mCustomizeAnimationInfo=" + mCustomAnimationInfo
                + '}';
    }
@@ -343,6 +358,7 @@ public final class BackNavigationInfo implements Parcelable {
        private IOnBackInvokedCallback mOnBackInvokedCallback = null;
        private boolean mPrepareRemoteAnimation;
        private CustomAnimationInfo mCustomAnimationInfo;
        private boolean mAnimationCallback = false;

        /**
         * @see BackNavigationInfo#getType()
@@ -387,6 +403,7 @@ public final class BackNavigationInfo implements Parcelable {
            mCustomAnimationInfo.mWindowAnimations = windowAnimations;
            return this;
        }

        /**
         * Set resources ids for customize activity animation.
         */
@@ -401,6 +418,14 @@ public final class BackNavigationInfo implements Parcelable {
            return this;
        }

        /**
         * @param isAnimationCallback whether the callback is {@link OnBackAnimationCallback}
         */
        public Builder setAnimationCallback(boolean isAnimationCallback) {
            mAnimationCallback = isAnimationCallback;
            return this;
        }

        /**
         * Builds and returns an instance of {@link BackNavigationInfo}
         */
@@ -408,6 +433,7 @@ public final class BackNavigationInfo implements Parcelable {
            return new BackNavigationInfo(mType, mOnBackNavigationDone,
                    mOnBackInvokedCallback,
                    mPrepareRemoteAnimation,
                    mAnimationCallback,
                    mCustomAnimationInfo);
        }
    }
+15 −2
Original line number Diff line number Diff line
@@ -28,15 +28,20 @@ public final class OnBackInvokedCallbackInfo implements Parcelable {
    @NonNull
    private final IOnBackInvokedCallback mCallback;
    private @OnBackInvokedDispatcher.Priority int mPriority;
    private final boolean mIsAnimationCallback;

    public OnBackInvokedCallbackInfo(@NonNull IOnBackInvokedCallback callback, int priority) {
    public OnBackInvokedCallbackInfo(@NonNull IOnBackInvokedCallback callback,
            int priority,
            boolean isAnimationCallback) {
        mCallback = callback;
        mPriority = priority;
        mIsAnimationCallback = isAnimationCallback;
    }

    private OnBackInvokedCallbackInfo(@NonNull Parcel in) {
        mCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
        mPriority = in.readInt();
        mIsAnimationCallback = in.readBoolean();
    }

    @Override
@@ -48,6 +53,7 @@ public final class OnBackInvokedCallbackInfo implements Parcelable {
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeStrongInterface(mCallback);
        dest.writeInt(mPriority);
        dest.writeBoolean(mIsAnimationCallback);
    }

    public static final Creator<OnBackInvokedCallbackInfo> CREATOR =
@@ -77,9 +83,16 @@ public final class OnBackInvokedCallbackInfo implements Parcelable {
        return mPriority;
    }

    public boolean isAnimationCallback() {
        return mIsAnimationCallback;
    }

    @Override
    public String toString() {
        return "OnBackInvokedCallbackInfo{"
                + "mCallback=" + mCallback + ", mPriority=" + mPriority + '}';
                + "mCallback=" + mCallback
                + ", mPriority=" + mPriority
                + ", mIsAnimationCallback=" + mIsAnimationCallback
                + '}';
    }
}
+4 −1
Original line number Diff line number Diff line
@@ -193,7 +193,10 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                                ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
                                        callback).getIOnBackInvokedCallback()
                                : new OnBackInvokedCallbackWrapper(callback);
                callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
                callbackInfo = new OnBackInvokedCallbackInfo(
                        iCallback,
                        priority,
                        callback instanceof OnBackAnimationCallback);
            }
            mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
        } catch (RemoteException e) {
+1 −0
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ class BackNavigationController {
                    backType = BackNavigationInfo.TYPE_CALLBACK;
                }
                infoBuilder.setOnBackInvokedCallback(callbackInfo.getCallback());
                infoBuilder.setAnimationCallback(callbackInfo.isAnimationCallback());
                mNavigationMonitor.startMonitor(window, navigationObserver);
            }

+38 −4
Original line number Diff line number Diff line
@@ -232,11 +232,36 @@ public class BackNavigationControllerTests extends WindowTestsBase {

        IOnBackInvokedCallback callback = createOnBackInvokedCallback();
        window.setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
                new OnBackInvokedCallbackInfo(
                        callback,
                        OnBackInvokedDispatcher.PRIORITY_DEFAULT,
                        /* isAnimationCallback = */ false));

        BackNavigationInfo backNavigationInfo = startBackNavigation();
        assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
        assertThat(backNavigationInfo.getType()).isEqualTo(BackNavigationInfo.TYPE_CALLBACK);
        assertThat(backNavigationInfo.isAnimationCallback()).isEqualTo(false);
        assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
    }

    @Test
    public void backInfoWithAnimationCallback() {
        WindowState window = createWindow(null, WindowManager.LayoutParams.TYPE_WALLPAPER,
                "Wallpaper");
        addToWindowMap(window, true);
        makeWindowVisibleAndDrawn(window);

        IOnBackInvokedCallback callback = createOnBackInvokedCallback();
        window.setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(
                        callback,
                        OnBackInvokedDispatcher.PRIORITY_DEFAULT,
                        /* isAnimationCallback = */ true));

        BackNavigationInfo backNavigationInfo = startBackNavigation();
        assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
        assertThat(backNavigationInfo.getType()).isEqualTo(BackNavigationInfo.TYPE_CALLBACK);
        assertThat(backNavigationInfo.isAnimationCallback()).isEqualTo(true);
        assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
    }

@@ -364,7 +389,10 @@ public class BackNavigationControllerTests extends WindowTestsBase {

        IOnBackInvokedCallback callback = createOnBackInvokedCallback();
        window.setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
                new OnBackInvokedCallbackInfo(
                        callback,
                        OnBackInvokedDispatcher.PRIORITY_DEFAULT,
                        /* isAnimationCallback = */ false));

        BackNavigationInfo backNavigationInfo = startBackNavigation();
        assertThat(backNavigationInfo).isNull();
@@ -450,14 +478,20 @@ public class BackNavigationControllerTests extends WindowTestsBase {
    private IOnBackInvokedCallback withSystemCallback(Task task) {
        IOnBackInvokedCallback callback = createOnBackInvokedCallback();
        task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_SYSTEM));
                new OnBackInvokedCallbackInfo(
                        callback,
                        OnBackInvokedDispatcher.PRIORITY_SYSTEM,
                        /* isAnimationCallback = */ false));
        return callback;
    }

    private IOnBackInvokedCallback withAppCallback(Task task) {
        IOnBackInvokedCallback callback = createOnBackInvokedCallback();
        task.getTopMostActivity().getTopChild().setOnBackInvokedCallbackInfo(
                new OnBackInvokedCallbackInfo(callback, OnBackInvokedDispatcher.PRIORITY_DEFAULT));
                new OnBackInvokedCallbackInfo(
                        callback,
                        OnBackInvokedDispatcher.PRIORITY_DEFAULT,
                        /* isAnimationCallback = */ false));
        return callback;
    }