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

Commit 1b8ed95f authored by Luca Zuccarini's avatar Luca Zuccarini
Browse files

Implement takeover functionality for the Home gesture on the Shell side.

This CL does a few things:
* Add a new registry for remotes so that they can be differentiated
  between "regular" and takeover remotes (requires registering twice for
  both functionalities).
* Add an API to Transitions to find a suitable handler to takeover a
  transition, and to TransitionHandler to handler the requests.
* Add an API to IRecentsAnimationController to hand off the recents
  animation, and to RecentsTransitionHandler to route it to the takeover
  remote correctly.

Bug: 323863002
Flag: ACONFIG com.android.systemui.shared.return_animation_framework_library DISABLED
Test: updated unit tests and tested manually
Change-Id: I58e2cccffa0da33260ae1e4b0d8a29f5965fa39a
parent 8e1ad154
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -17,11 +17,13 @@
package android.view;

import android.app.ActivityManager;
import android.graphics.GraphicBuffer;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.graphics.GraphicBuffer;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
import android.window.WindowAnimationState;

import com.android.internal.os.IResultReceiver;

@@ -160,4 +162,17 @@ interface IRecentsAnimationController {
     * @param duration the duration of the app launch animation
     */
    void animateNavigationBarToApp(long duration);

    /**
     * Hand off the ongoing animation of a set of remote targets, to be run by another handler using
     * the given starting parameters.
     *
     * Once the handoff is complete, operations on the old leashes for the given targets as well as
     * callbacks will become no-ops.
     *
     * The number of targets MUST match the number of states, and each state MUST match the target
     * at the same index.
     */
    oneway void handOffAnimation(in RemoteAnimationTarget[] targets,
                    in WindowAnimationState[] states);
}
+1 −0
Original line number Diff line number Diff line
@@ -210,6 +210,7 @@ android_library {
        "androidx.recyclerview_recyclerview",
        "kotlinx-coroutines-android",
        "kotlinx-coroutines-core",
        "//frameworks/libs/systemui:com_android_systemui_shared_flags_lib",
        "//frameworks/libs/systemui:iconloader_base",
        "com_android_wm_shell_flags_lib",
        "com.android.window.flags.window-aconfig-java",
+9 −2
Original line number Diff line number Diff line
@@ -28,13 +28,14 @@ import com.android.wm.shell.shared.IHomeTransitionListener;
interface IShellTransitions {

    /**
     * Registers a remote transition handler.
     * Registers a remote transition handler for all operations excluding takeovers (see
     * registerRemoteForTakeover()).
     */
    oneway void registerRemote(in TransitionFilter filter,
            in RemoteTransition remoteTransition) = 1;

    /**
     * Unregisters a remote transition handler.
     * Unregisters a remote transition handler for all operations.
     */
    oneway void unregisterRemote(in RemoteTransition remoteTransition) = 2;

@@ -52,4 +53,10 @@ interface IShellTransitions {
     * Returns a container surface for the home root task.
     */
    SurfaceControl getHomeTaskOverlayContainer() = 5;

    /**
     * Registers a remote transition for takeover operations only.
     */
    oneway void registerRemoteForTakeover(in TransitionFilter filter,
            in RemoteTransition remoteTransition) = 6;
}
+9 −2
Original line number Diff line number Diff line
@@ -28,13 +28,20 @@ import com.android.wm.shell.shared.annotations.ExternalThread;
@ExternalThread
public interface ShellTransitions {
    /**
     * Registers a remote transition.
     * Registers a remote transition for all operations excluding takeovers (see
     * {@link ShellTransitions#registerRemoteForTakeover(TransitionFilter, RemoteTransition)}).
     */
    default void registerRemote(@NonNull TransitionFilter filter,
            @NonNull RemoteTransition remoteTransition) {}

    /**
     * Unregisters a remote transition.
     * Registers a remote transition for takeover operations only.
     */
    default void registerRemoteForTakeover(@NonNull TransitionFilter filter,
            @NonNull RemoteTransition remoteTransition) {}

    /**
     * Unregisters a remote transition for all operations.
     */
    default void unregisterRemote(@NonNull RemoteTransition remoteTransition) {}
}
+65 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.view.WindowManager.TRANSIT_SLEEP;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_TRANSLUCENT;

import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION;
import static com.android.wm.shell.util.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;

import android.annotation.Nullable;
@@ -54,6 +55,7 @@ import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
import android.window.WindowAnimationState;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

@@ -283,6 +285,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
        private IBinder mTransition = null;
        private boolean mKeyguardLocked = false;
        private boolean mWillFinishToHome = false;
        private Transitions.TransitionHandler mTakeoverHandler = null;

        /** The animation is idle, waiting for the user to choose a task to switch to. */
        private static final int STATE_NORMAL = 0;
@@ -576,9 +579,13 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                    "Applying transaction=%d", t.getId());
            t.apply();
            Bundle b = new Bundle(1 /*capacity*/);

            mTakeoverHandler = mTransitions.getHandlerForTakeover(mTransition, info);

            Bundle b = new Bundle(2 /*capacity*/);
            b.putParcelable(KEY_EXTRA_SPLIT_BOUNDS,
                    mRecentTasksController.getSplitBoundsForTaskId(closingSplitTaskId));
            b.putBoolean(KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION, mTakeoverHandler != null);
            try {
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.start: calling onAnimationStart with %d apps",
@@ -597,6 +604,63 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
            return true;
        }

        @Override
        public void handOffAnimation(
                RemoteAnimationTarget[] targets, WindowAnimationState[] states) {
            mExecutor.execute(() -> {
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.handOffAnimation", mInstanceId);

                if (mTakeoverHandler == null) {
                    Slog.e(TAG, "Tried to hand off an animation without a valid takeover "
                            + "handler.");
                    return;
                }

                if (targets.length != states.length) {
                    Slog.e(TAG, "Tried to hand off an animation, but the number of targets "
                            + "(" + targets.length + ") doesn't match the number of states "
                            + "(" + states.length + ")");
                    return;
                }

                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.handOffAnimation: got %d states for %d "
                                + "changes", mInstanceId, states.length, mInfo.getChanges().size());
                WindowAnimationState[] updatedStates =
                        new WindowAnimationState[mInfo.getChanges().size()];

                // Ensure that the ordering of animation states is the same as that of  matching
                // changes in mInfo. prefixOrderIndex is set up in reverse order to that of the
                // changes, so that's what we use to get to the correct ordering.
                for (int i = 0; i < targets.length; i++) {
                    RemoteAnimationTarget target = targets[i];
                    updatedStates[updatedStates.length - target.prefixOrderIndex] = states[i];
                }

                Transitions.TransitionFinishCallback finishCB = mFinishCB;
                // Reset the callback here, so any stray calls that aren't coming from the new
                // handler are ignored.
                mFinishCB = null;

                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                        "[%d] RecentsController.handOffAnimation: calling "
                                + "takeOverAnimation with %d states", mInstanceId,
                        updatedStates.length);
                mTakeoverHandler.takeOverAnimation(
                        mTransition, mInfo, new SurfaceControl.Transaction(),
                        wct -> {
                            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                    "[%d] RecentsController.handOffAnimation: finish "
                                            + "callback", mInstanceId);
                            // Set the callback once again so we can finish correctly.
                            mFinishCB = finishCB;
                            finishInner(true /* toHome */, false /* userLeave */,
                                    null /* finishCb */);
                        }, updatedStates);
            });
        }

        /**
         * Updates this controller when a new transition is requested mid-recents transition.
         */
Loading