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

Commit 8fcc92bb authored by Arthur Hung's avatar Arthur Hung
Browse files

Refactor back navigation animtion (1/2)

In previous design, it would create all necessary leashes when starting
back navigation, and they would be carried by `BackNavigationInfo` and
`BackEvent` and would finally deliver to the shell and animator side.

In this CL, we will use the adapter that wraps a back animation runner
to deliver all leashes in next surface placement after back navigation
has started.

In shell side, every animator should be registered by type, so the
adapter could deliver leashes via IRemoteAnimationRunner to the
target animator, and invoke callback when it finished.

This also eliminated all unecessary fields from `BackNavigationInfo` and
`BackEvent`.

Bug: 241808055
Test: atest BackNavigationControllerTests BackAnimationControllerTest
      BackNavigationTest
Change-Id: I8bbec0d8d9631110c3d2788d958b50ae487520a7
parent bb25387f
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import android.view.IWindowFocusObserver;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
import android.window.IWindowOrganizerController;
import android.window.BackAnimationAdapter;
import android.window.BackNavigationInfo;
import android.window.SplashScreenView;
import com.android.internal.app.IVoiceInteractor;
@@ -352,9 +353,10 @@ interface IActivityTaskManager {
    /**
     * Prepare the back navigation in the server. This setups the leashed for sysui to animate
     * the back gesture and returns the data needed for the animation.
     * @param requestAnimation true if the caller wishes to animate the back navigation
     * @param focusObserver a remote callback to nofify shell when the focused window lost focus.
     * @param adaptor a remote animation to be run for the back navigation plays the animation.
     * @return Returns the back navigation info.
     */
    android.window.BackNavigationInfo startBackNavigation(in boolean requestAnimation,
            in IWindowFocusObserver focusObserver);
    android.window.BackNavigationInfo startBackNavigation(
            in IWindowFocusObserver focusObserver, in BackAnimationAdapter adaptor);
}
+22 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.window;

/**
 * @hide
 */
parcelable BackAnimationAdapter;
 No newline at end of file
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.window;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Object that describes how to run a remote back animation.
 *
 * @hide
 */
public class BackAnimationAdapter implements Parcelable {
    private final IBackAnimationRunner mRunner;

    public BackAnimationAdapter(IBackAnimationRunner runner) {
        mRunner = runner;
    }

    public BackAnimationAdapter(Parcel in) {
        mRunner = IBackAnimationRunner.Stub.asInterface(in.readStrongBinder());
    }

    public IBackAnimationRunner getRunner() {
        return mRunner;
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStrongInterface(mRunner);
    }

    public static final @android.annotation.NonNull Creator<BackAnimationAdapter> CREATOR =
            new Creator<BackAnimationAdapter>() {
        public BackAnimationAdapter createFromParcel(Parcel in) {
            return new BackAnimationAdapter(in);
        }

        public BackAnimationAdapter[] newArray(int size) {
            return new BackAnimationAdapter[size];
        }
    };
}
+1 −22
Original line number Diff line number Diff line
@@ -18,10 +18,8 @@ package android.window;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.RemoteAnimationTarget;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -52,8 +50,6 @@ public class BackEvent implements Parcelable {

    @SwipeEdge
    private final int mSwipeEdge;
    @Nullable
    private final RemoteAnimationTarget mDepartingAnimationTarget;

    /**
     * Creates a new {@link BackEvent} instance.
@@ -62,16 +58,12 @@ public class BackEvent implements Parcelable {
     * @param touchY Absolute Y location of the touch point of this event.
     * @param progress Value between 0 and 1 on how far along the back gesture is.
     * @param swipeEdge Indicates which edge the swipe starts from.
     * @param departingAnimationTarget The remote animation target of the departing application
     *                                 window.
     */
    public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge,
            @Nullable RemoteAnimationTarget departingAnimationTarget) {
    public BackEvent(float touchX, float touchY, float progress, @SwipeEdge int swipeEdge) {
        mTouchX = touchX;
        mTouchY = touchY;
        mProgress = progress;
        mSwipeEdge = swipeEdge;
        mDepartingAnimationTarget = departingAnimationTarget;
    }

    private BackEvent(@NonNull Parcel in) {
@@ -79,7 +71,6 @@ public class BackEvent implements Parcelable {
        mTouchY = in.readFloat();
        mProgress = in.readFloat();
        mSwipeEdge = in.readInt();
        mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR);
    }

    public static final Creator<BackEvent> CREATOR = new Creator<BackEvent>() {
@@ -105,7 +96,6 @@ public class BackEvent implements Parcelable {
        dest.writeFloat(mTouchY);
        dest.writeFloat(mProgress);
        dest.writeInt(mSwipeEdge);
        dest.writeTypedObject(mDepartingAnimationTarget, flags);
    }

    /**
@@ -136,16 +126,6 @@ public class BackEvent implements Parcelable {
        return mSwipeEdge;
    }

    /**
     * Returns the {@link RemoteAnimationTarget} of the top departing application window,
     * or {@code null} if the top window should not be moved for the current type of back
     * destination.
     */
    @Nullable
    public RemoteAnimationTarget getDepartingAnimationTarget() {
        return mDepartingAnimationTarget;
    }

    @Override
    public String toString() {
        return "BackEvent{"
@@ -153,7 +133,6 @@ public class BackEvent implements Parcelable {
                + ", mTouchY=" + mTouchY
                + ", mProgress=" + mProgress
                + ", mSwipeEdge" + mSwipeEdge
                + ", mDepartingAnimationTarget" + mDepartingAnimationTarget
                + "}";
    }
}
+28 −133
Original line number Diff line number Diff line
@@ -19,14 +19,10 @@ package android.window;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.hardware.HardwareBuffer;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteCallback;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;

/**
 * Information to be sent to SysUI about a back event.
@@ -84,75 +80,50 @@ public final class BackNavigationInfo implements Parcelable {
            TYPE_CROSS_TASK,
            TYPE_CALLBACK
    })
    @interface BackTargetType {
    public @interface BackTargetType {
    }

    private final int mType;
    @Nullable
    private final RemoteAnimationTarget mDepartingAnimationTarget;
    @Nullable
    private final SurfaceControl mScreenshotSurface;
    @Nullable
    private final HardwareBuffer mScreenshotBuffer;
    @Nullable
    private final RemoteCallback mOnBackNavigationDone;
    @Nullable
    private final WindowConfiguration mTaskWindowConfiguration;
    @Nullable
    private final IOnBackInvokedCallback mOnBackInvokedCallback;
    private final boolean mPrepareRemoteAnimation;

    /**
     * Create a new {@link BackNavigationInfo} instance.
     *
     * @param type                    The {@link BackTargetType} of the destination (what will be
     *                                displayed after the back action).
     * @param departingAnimationTarget  The remote animation target, containing a leash to animate
     *                                  away the departing window. The consumer of the leash is
     *                                  responsible for removing it.
     * @param screenshotSurface       The screenshot of the previous activity to be displayed.
     * @param screenshotBuffer        A buffer containing a screenshot used to display the activity.
     *                                See {@link  #getScreenshotHardwareBuffer()} for information
     *                                about nullity.
     * @param taskWindowConfiguration The window configuration of the Task being animated beneath.
     * @param onBackNavigationDone    The callback to be called once the client is done with the
     *                                back preview.
     * @param onBackInvokedCallback   The back callback registered by the current top level window.
     * @param isPrepareRemoteAnimation  Return whether the core is preparing a back gesture
     *                                  animation, if true, the caller of startBackNavigation should
     *                                  be expected to receive an animation start callback.
     */
    private BackNavigationInfo(@BackTargetType int type,
            @Nullable RemoteAnimationTarget departingAnimationTarget,
            @Nullable SurfaceControl screenshotSurface,
            @Nullable HardwareBuffer screenshotBuffer,
            @Nullable WindowConfiguration taskWindowConfiguration,
            @Nullable RemoteCallback onBackNavigationDone,
            @Nullable IOnBackInvokedCallback onBackInvokedCallback) {
            @Nullable IOnBackInvokedCallback onBackInvokedCallback,
            boolean isPrepareRemoteAnimation) {
        mType = type;
        mDepartingAnimationTarget = departingAnimationTarget;
        mScreenshotSurface = screenshotSurface;
        mScreenshotBuffer = screenshotBuffer;
        mTaskWindowConfiguration = taskWindowConfiguration;
        mOnBackNavigationDone = onBackNavigationDone;
        mOnBackInvokedCallback = onBackInvokedCallback;
        mPrepareRemoteAnimation = isPrepareRemoteAnimation;
    }

    private BackNavigationInfo(@NonNull Parcel in) {
        mType = in.readInt();
        mDepartingAnimationTarget = in.readTypedObject(RemoteAnimationTarget.CREATOR);
        mScreenshotSurface = in.readTypedObject(SurfaceControl.CREATOR);
        mScreenshotBuffer = in.readTypedObject(HardwareBuffer.CREATOR);
        mTaskWindowConfiguration = in.readTypedObject(WindowConfiguration.CREATOR);
        mOnBackNavigationDone = in.readTypedObject(RemoteCallback.CREATOR);
        mOnBackInvokedCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
        mPrepareRemoteAnimation = in.readBoolean();
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mType);
        dest.writeTypedObject(mDepartingAnimationTarget, flags);
        dest.writeTypedObject(mScreenshotSurface, flags);
        dest.writeTypedObject(mScreenshotBuffer, flags);
        dest.writeTypedObject(mTaskWindowConfiguration, flags);
        dest.writeTypedObject(mOnBackNavigationDone, flags);
        dest.writeStrongInterface(mOnBackInvokedCallback);
        dest.writeBoolean(mPrepareRemoteAnimation);
    }

    /**
@@ -164,49 +135,6 @@ public final class BackNavigationInfo implements Parcelable {
        return mType;
    }

    /**
     * Returns a {@link RemoteAnimationTarget}, containing a leash to the top window container
     * that needs to be animated. This can be null if the back animation is controlled by
     * the application.
     */
    @Nullable
    public RemoteAnimationTarget getDepartingAnimationTarget() {
        return mDepartingAnimationTarget;
    }

    /**
     * Returns the {@link SurfaceControl} that should be used to display a screenshot of the
     * previous activity.
     */
    @Nullable
    public SurfaceControl getScreenshotSurface() {
        return mScreenshotSurface;
    }

    /**
     * Returns the {@link HardwareBuffer} containing the screenshot the activity about to be
     * shown. This can be null if one of the following conditions is met:
     * <ul>
     *     <li>The screenshot is not available
     *     <li> The previous activity is the home screen ( {@link  #TYPE_RETURN_TO_HOME}
     *     <li> The current window is a dialog ({@link  #TYPE_DIALOG_CLOSE}
     *     <li> The back animation is controlled by the application
     * </ul>
     */
    @Nullable
    public HardwareBuffer getScreenshotHardwareBuffer() {
        return mScreenshotBuffer;
    }

    /**
     * Returns the {@link WindowConfiguration} of the current task. This is null when the top
     * application is controlling the back animation.
     */
    @Nullable
    public WindowConfiguration getTaskWindowConfiguration() {
        return mTaskWindowConfiguration;
    }

    /**
     * Returns the {@link OnBackInvokedCallback} of the top level window or null if
     * the client didn't register a callback.
@@ -221,6 +149,13 @@ public final class BackNavigationInfo implements Parcelable {
        return mOnBackInvokedCallback;
    }

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

    /**
     * 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.
@@ -256,10 +191,6 @@ public final class BackNavigationInfo implements Parcelable {
    public String toString() {
        return "BackNavigationInfo{"
                + "mType=" + typeToString(mType) + " (" + mType + ")"
                + ", mDepartingAnimationTarget=" + mDepartingAnimationTarget
                + ", mScreenshotSurface=" + mScreenshotSurface
                + ", mTaskWindowConfiguration= " + mTaskWindowConfiguration
                + ", mScreenshotBuffer=" + mScreenshotBuffer
                + ", mOnBackNavigationDone=" + mOnBackNavigationDone
                + ", mOnBackInvokedCallback=" + mOnBackInvokedCallback
                + '}';
@@ -291,21 +222,12 @@ public final class BackNavigationInfo implements Parcelable {
     */
    @SuppressWarnings("UnusedReturnValue") // Builder pattern
    public static class Builder {

        private int mType = TYPE_UNDEFINED;
        @Nullable
        private RemoteAnimationTarget mDepartingAnimationTarget = null;
        @Nullable
        private SurfaceControl mScreenshotSurface = null;
        @Nullable
        private HardwareBuffer mScreenshotBuffer = null;
        @Nullable
        private WindowConfiguration mTaskWindowConfiguration = null;
        @Nullable
        private RemoteCallback mOnBackNavigationDone = null;
        @Nullable
        private IOnBackInvokedCallback mOnBackInvokedCallback = null;

        private boolean mPrepareRemoteAnimation;
        /**
         * @see BackNavigationInfo#getType()
         */
@@ -314,40 +236,6 @@ public final class BackNavigationInfo implements Parcelable {
            return this;
        }

        /**
         * @see BackNavigationInfo#getDepartingAnimationTarget
         */
        public Builder setDepartingAnimationTarget(
                @Nullable RemoteAnimationTarget departingAnimationTarget) {
            mDepartingAnimationTarget = departingAnimationTarget;
            return this;
        }

        /**
         * @see BackNavigationInfo#getScreenshotSurface
         */
        public Builder setScreenshotSurface(@Nullable SurfaceControl screenshotSurface) {
            mScreenshotSurface = screenshotSurface;
            return this;
        }

        /**
         * @see BackNavigationInfo#getScreenshotHardwareBuffer()
         */
        public Builder setScreenshotBuffer(@Nullable HardwareBuffer screenshotBuffer) {
            mScreenshotBuffer = screenshotBuffer;
            return this;
        }

        /**
         * @see BackNavigationInfo#getTaskWindowConfiguration
         */
        public Builder setTaskWindowConfiguration(
                @Nullable WindowConfiguration taskWindowConfiguration) {
            mTaskWindowConfiguration = taskWindowConfiguration;
            return this;
        }

        /**
         * @see BackNavigationInfo#onBackNavigationFinished(boolean)
         */
@@ -365,13 +253,20 @@ public final class BackNavigationInfo implements Parcelable {
            return this;
        }

        /**
         * @param prepareRemoteAnimation Whether core prepare animation for shell.
         */
        public Builder setPrepareRemoteAnimation(boolean prepareRemoteAnimation) {
            mPrepareRemoteAnimation = prepareRemoteAnimation;
            return this;
        }

        /**
         * Builds and returns an instance of {@link BackNavigationInfo}
         */
        public BackNavigationInfo build() {
            return new BackNavigationInfo(mType, mDepartingAnimationTarget, mScreenshotSurface,
                    mScreenshotBuffer, mTaskWindowConfiguration, mOnBackNavigationDone,
                    mOnBackInvokedCallback);
            return new BackNavigationInfo(mType, mOnBackNavigationDone,
                    mOnBackInvokedCallback, mPrepareRemoteAnimation);
        }
    }
}
Loading