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

Commit b1bbc0f7 authored by Vinit Nayak's avatar Vinit Nayak Committed by Evan Rosky
Browse files

Changes to use new startTasks API

When shell transitions is enabled, this will use the
newer multi-task-launch api and control the animation.

There is no actual animation yet, this just adds the
infrastructure.

Bug: 182002789
Test: enable developer option and enter split via recents
Change-Id: If5be104a86e7b5f743f85efed20b0d2bf1b8bfd1
parent 7f463d33
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -219,7 +219,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
        mSplitPlaceholderView = findViewById(R.id.split_placeholder);
        RecentsView overviewPanel = (RecentsView) getOverviewPanel();
        mSplitPlaceholderView.init(
                new SplitSelectStateController(SystemUiProxy.INSTANCE.get(this))
                new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this))
        );
        overviewPanel.init(mActionsView, mSplitPlaceholderView);
        mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
+1 −2
Original line number Diff line number Diff line
@@ -108,8 +108,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {

        SplitPlaceholderView splitPlaceholderView = findViewById(R.id.split_placeholder);
        splitPlaceholderView.init(
                new SplitSelectStateController(
                        SystemUiProxy.INSTANCE.get(this))
                new SplitSelectStateController(mUiHandler, SystemUiProxy.INSTANCE.get(this))
        );

        mDragLayer.recreateControllers();
+15 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.util.Log;
import android.view.MotionEvent;

import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteTransitionCompat;
@@ -491,6 +492,20 @@ public class SystemUiProxy implements ISystemUiProxy,
        }
    }

    /** Start multiple tasks in split-screen simultaneously. */
    public void startTasks(int mainTaskId, Bundle mainOptions, int sideTaskId, Bundle sideOptions,
            @SplitConfigurationOptions.StagePosition int sidePosition,
            RemoteTransitionCompat remoteTransition) {
        if (mSystemUiProxy != null) {
            try {
                mSplitScreen.startTasks(mainTaskId, mainOptions, sideTaskId, sideOptions,
                        sidePosition, remoteTransition.getTransition());
            } catch (RemoteException e) {
                Log.w(TAG, "Failed call startTask");
            }
        }
    }

    public void startShortcut(String packageName, String shortcutId, int stage, int position,
            Bundle options, UserHandle user) {
        if (mSplitScreen != null) {
+46 −1
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.quickstep;

import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_FRONT;

import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -47,7 +50,9 @@ import android.graphics.Matrix.ScaleToFit;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.view.SurfaceControl;
import android.view.View;
import android.window.TransitionInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -352,7 +357,47 @@ public final class TaskViewUtils {
     * device is considered in multiWindowMode and things like insets and stuff change
     * and calculations have to be adjusted in the animations for that
     */
    public static void composeRecentsSplitLaunchAnimator(@NonNull AnimatorSet anim,
    public static void composeRecentsSplitLaunchAnimator(@NonNull TaskView initialView,
            @NonNull TaskView v, @NonNull TransitionInfo transitionInfo,
            SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {

        final TransitionInfo.Change[] splitRoots = new TransitionInfo.Change[2];
        for (int i = 0; i < transitionInfo.getChanges().size(); ++i) {
            final TransitionInfo.Change change = transitionInfo.getChanges().get(i);
            final int taskId = change.getTaskInfo() != null ? change.getTaskInfo().taskId : -1;
            final int mode = change.getMode();
            // Find the target tasks' root tasks since those are the split stages that need to
            // be animated (the tasks themselves are children and thus inherit animation).
            if (taskId == initialView.getTask().key.id || taskId == v.getTask().key.id) {
                if (!(mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
                    throw new IllegalStateException(
                            "Expected task to be showing, but it is " + mode);
                }
                if (change.getParent() == null) {
                    throw new IllegalStateException("Initiating multi-split launch but the split"
                            + "root of " + taskId + " is already visible or has broken hierarchy.");
                }
                splitRoots[taskId == initialView.getTask().key.id ? 0 : 1] =
                        transitionInfo.getChange(change.getParent());
            }
        }

        // This is where we should animate the split roots. For now, though, just make them visible.
        for (int i = 0; i < 2; ++i) {
            t.show(splitRoots[i].getLeash());
            t.setAlpha(splitRoots[i].getLeash(), 1.f);
        }

        // This contains the initial state (before animation), so apply this at the beginning of
        // the animation.
        t.apply();

        // Once there is an animation, this should be called AFTER the animation completes.
        finishCallback.run();
    }

    /** Legacy version (until shell transitions are enabled) */
    public static void composeRecentsSplitLaunchAnimatorLegacy(@NonNull AnimatorSet anim,
            @NonNull TaskView v, @NonNull RemoteAnimationTargetCompat[] appTargets,
            @NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
            @NonNull RemoteAnimationTargetCompat[] nonAppTargets, boolean launcherClosing,
+51 −2
Original line number Diff line number Diff line
@@ -16,11 +16,17 @@

package com.android.quickstep.util;

import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;

import android.animation.AnimatorSet;
import android.app.ActivityOptions;
import android.os.Handler;
import android.os.Looper;
import android.util.Pair;
import android.view.SurfaceControl;
import android.window.TransitionInfo;

import androidx.annotation.Nullable;

@@ -31,12 +37,15 @@ import com.android.launcher3.WrappedAnimationRunnerImpl;
import com.android.launcher3.WrappedLauncherAnimationRunner;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.RemoteTransitionCompat;
import com.android.systemui.shared.system.RemoteTransitionRunner;

/**
 * Represent data needed for the transient state when user has selected one app for split screen
@@ -47,9 +56,11 @@ public class SplitSelectStateController {
    private final SystemUiProxy mSystemUiProxy;
    private TaskView mInitialTaskView;
    private SplitPositionOption mInitialPosition;
    private final Handler mHandler;

    public SplitSelectStateController(SystemUiProxy systemUiProxy) {
    public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
        mSystemUiProxy = systemUiProxy;
        mHandler = handler;
    }

    /**
@@ -64,6 +75,19 @@ public class SplitSelectStateController {
     * To be called after second task selected
     */
    public void setSecondTaskId(TaskView taskView) {
        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
            // Assume initial task is for top/left part of screen
            final int[] taskIds = mInitialPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT
                    ? new int[]{mInitialTaskView.getTask().key.id, taskView.getTask().key.id}
                    : new int[]{taskView.getTask().key.id, mInitialTaskView.getTask().key.id};

            RemoteSplitLaunchAnimationRunner animationRunner =
                    new RemoteSplitLaunchAnimationRunner(mInitialTaskView, taskView);
            mSystemUiProxy.startTasks(taskIds[0], null /* mainOptions */, taskIds[1],
                    null /* sideOptions */, STAGE_POSITION_BOTTOM_OR_RIGHT,
                    new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR));
            return;
        }
        // Assume initial mInitialTaskId is for top/left part of screen
        WrappedAnimationRunnerImpl initialSplitRunnerWrapped =  new SplitLaunchAnimationRunner(
                mInitialTaskView, 0);
@@ -96,6 +120,30 @@ public class SplitSelectStateController {
    }

    /**
     * Requires Shell Transitions
     */
    private class RemoteSplitLaunchAnimationRunner implements RemoteTransitionRunner {

        private final TaskView mInitialTaskView;
        private final TaskView mTaskView;

        RemoteSplitLaunchAnimationRunner(TaskView initialTaskView, TaskView taskView) {
            mInitialTaskView = initialTaskView;
            mTaskView = taskView;
        }

        @Override
        public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
                Runnable finishCallback) {
            TaskViewUtils.composeRecentsSplitLaunchAnimator(mInitialTaskView, mTaskView,
                    info, t, finishCallback);
            // After successful launch, call resetState
            resetState();
        }
    }

    /**
     * LEGACY
     * @return the opposite stage and position from the {@param position} provided as first and
     *         second object, respectively
     * Ex. If position is has stage = Main and position = Top/Left, this will return
@@ -109,6 +157,7 @@ public class SplitSelectStateController {
    }

    /**
     * LEGACY
     * Remote animation runner for animation to launch an app.
     */
    private class SplitLaunchAnimationRunner implements WrappedAnimationRunnerImpl {
@@ -129,7 +178,7 @@ public class SplitSelectStateController {
                LauncherAnimationRunner.AnimationResult result) {
            AnimatorSet anim = new AnimatorSet();
            BaseQuickstepLauncher activity = BaseActivity.fromContext(mV.getContext());
            TaskViewUtils.composeRecentsSplitLaunchAnimator(anim, mV,
            TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(anim, mV,
                    appTargets, wallpaperTargets, nonAppTargets, true, activity.getStateManager(),
                    activity.getDepthController(), mTargetState);
            result.setAnimation(anim, activity);