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

Commit 69ee1b9c authored by Vinit Nayak's avatar Vinit Nayak
Browse files

Handle fullscreen app launchs in split init flow for SplitSelectDataHolder

* SystemUi split APIs are overloaded to launch fullscreen tasks
as well, break that out into a separate method for clarity
* Have SplitSelectDataHolder also special case fullscreen launches

Bug: 283045822
Test: Launched various combinations of split tasks,
also tapped on initial view to see fullscreen launch with tasks
and intents
Flag: none

Change-Id: If3de9784b72e0f5f27f1b6d97cbf835b8f5391de
parent 47ab6f8b
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -61,7 +61,8 @@ class SplitSelectDataHolder(
     */
    companion object {
        @IntDef(SPLIT_TASK_TASK, SPLIT_TASK_PENDINGINTENT, SPLIT_TASK_SHORTCUT,
                SPLIT_PENDINGINTENT_TASK, SPLIT_PENDINGINTENT_PENDINGINTENT, SPLIT_SHORTCUT_TASK)
                SPLIT_PENDINGINTENT_TASK, SPLIT_PENDINGINTENT_PENDINGINTENT, SPLIT_SHORTCUT_TASK,
                SPLIT_SINGLE_TASK_FULLSCREEN, SPLIT_SINGLE_INTENT_FULLSCREEN)
        @Retention(AnnotationRetention.SOURCE)
        annotation class SplitLaunchType

@@ -71,6 +72,10 @@ class SplitSelectDataHolder(
        const val SPLIT_PENDINGINTENT_TASK = 3
        const val SPLIT_SHORTCUT_TASK = 4
        const val SPLIT_PENDINGINTENT_PENDINGINTENT = 5

        // Non-split edge case of launching the initial selected task as a fullscreen task
        const val SPLIT_SINGLE_TASK_FULLSCREEN = 6
        const val SPLIT_SINGLE_INTENT_FULLSCREEN = 7
    }


@@ -190,7 +195,7 @@ class SplitSelectDataHolder(

    /**
     * @return [SplitLaunchData] with the necessary fields populated as determined by
     *   [SplitLaunchData.splitLaunchType]
     *   [SplitLaunchData.splitLaunchType]. This is to be used for launching splitscreen
     */
    fun getSplitLaunchData() : SplitLaunchData {
        // Convert all intents to shortcut infos to see if determine if we launch shortcut or intent
@@ -201,6 +206,24 @@ class SplitSelectDataHolder(
            initialStagePosition = getOppositeStagePosition(initialStagePosition)
        }

        return generateSplitLaunchData(splitLaunchType)
    }

    /**
     * @return [SplitLaunchData] with the necessary fields populated as determined by
     *   [SplitLaunchData.splitLaunchType]. This is to be used for launching an initially selected
     *   split task in fullscreen
     */
    fun getFullscreenLaunchData() : SplitLaunchData {
        // Convert all intents to shortcut infos to see if determine if we launch shortcut or intent
        convertIntentsToFinalTypes()
        val splitLaunchType = if (initialTaskId != INVALID_TASK_ID) SPLIT_SINGLE_TASK_FULLSCREEN
        else SPLIT_SINGLE_INTENT_FULLSCREEN

        return generateSplitLaunchData(splitLaunchType)
    }

    private fun generateSplitLaunchData(@SplitLaunchType splitLaunchType: Int) : SplitLaunchData {
        return SplitLaunchData(
                splitLaunchType,
                initialTaskId,
+84 −30
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@ import static com.android.launcher3.util.SplitConfigurationOptions.getOppositeSt
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_PENDINGINTENT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_PENDINGINTENT_TASK;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SHORTCUT_TASK;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SINGLE_INTENT_FULLSCREEN;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_SINGLE_TASK_FULLSCREEN;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDINGINTENT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;
@@ -324,11 +326,8 @@ public class SplitSelectStateController {
        }
        boolean hasSecondaryPendingIntent = mSecondPendingIntent != null;
        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
            final RemoteSplitLaunchTransitionRunner animationRunner =
                    new RemoteSplitLaunchTransitionRunner(taskId1, taskId2, callback);
            final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
                    ActivityThread.currentActivityThread().getApplicationThread(),
                    "LaunchSplitPair");
            final RemoteTransition remoteTransition = getShellRemoteTransition(taskId1, taskId2,
                    callback);
            if (intent1 == null && (intent2 == null && !hasSecondaryPendingIntent)) {
                mSystemUiProxy.startTasks(taskId1, options1.toBundle(), taskId2,
                        null /* options2 */, stagePosition, splitRatio, remoteTransition,
@@ -351,11 +350,8 @@ public class SplitSelectStateController {
                        shellInstanceId);
            }
        } else {
            final RemoteSplitLaunchAnimationRunner animationRunner =
                    new RemoteSplitLaunchAnimationRunner(taskId1, taskId2, callback);
            final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
                    animationRunner, 300, 150,
                    ActivityThread.currentActivityThread().getApplicationThread());
            final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(taskId1, taskId2,
                    callback);

            if (intent1 == null && (intent2 == null && !hasSecondaryPendingIntent)) {
                mSystemUiProxy.startTasksWithLegacyTransition(taskId1, options1.toBundle(),
@@ -402,11 +398,8 @@ public class SplitSelectStateController {
        Bundle optionsBundle = options1.toBundle();

        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
            final RemoteSplitLaunchTransitionRunner animationRunner =
                    new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
            final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
                    ActivityThread.currentActivityThread().getApplicationThread(),
                    "LaunchSplitPair");
            final RemoteTransition remoteTransition = getShellRemoteTransition(firstTaskId,
                    secondTaskId, callback);
            switch (launchData.getSplitLaunchType()) {
                case SPLIT_TASK_TASK ->
                        mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
@@ -440,11 +433,8 @@ public class SplitSelectStateController {
                                remoteTransition, shellInstanceId);
            }
        } else {
            final RemoteSplitLaunchAnimationRunner animationRunner =
                    new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
            final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
                    animationRunner, 300, 150,
                    ActivityThread.currentActivityThread().getApplicationThread());
            final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId, secondTaskId,
                    callback);
            switch (launchData.getSplitLaunchType()) {
                case SPLIT_TASK_TASK ->
                        mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
@@ -501,24 +491,88 @@ public class SplitSelectStateController {
        Bundle optionsBundle = options1.toBundle();

        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
            final RemoteTransition remoteTransition = getShellRemoteTransition(firstTaskId,
                    secondTaskId, callback);
            mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
                    null /* options2 */, stagePosition, splitRatio,
                    remoteTransition, null /*shellInstanceId*/);
        } else {
            final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
                    secondTaskId, callback);
            mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
                    secondTaskId, null /* options2 */, stagePosition,
                    splitRatio, adapter, null /*shellInstanceId*/);
        }
    }

    /**
     * Launches the initially selected task/intent in fullscreen (note the same SystemUi APIs are
     * used as {@link #launchSplitTasks(Consumer)} because they are overloaded to launch both
     * split and fullscreen tasks)
     */
    public void launchInitialAppFullscreen(Consumer<Boolean> callback) {
        if (!FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
            launchSplitTasks(callback);
            return;
        }

        final ActivityOptions options1 = ActivityOptions.makeBasic();
        SplitSelectDataHolder.SplitLaunchData launchData =
                mSplitSelectDataHolder.getFullscreenLaunchData();
        int firstTaskId = launchData.getInitialTaskId();
        int secondTaskId = launchData.getSecondTaskId();
        PendingIntent firstPI = launchData.getInitialPendingIntent();
        int firstUserId = launchData.getInitialUserId();
        int initialStagePosition = launchData.getInitialStagePosition();
        Bundle optionsBundle = options1.toBundle();

        final RemoteSplitLaunchTransitionRunner animationRunner =
                new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
        final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
                ActivityThread.currentActivityThread().getApplicationThread(),
                "LaunchSplitPair");
            mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId,
                    null /* options2 */, stagePosition, splitRatio,
                    remoteTransition, null /*shellInstanceId*/);
        Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
                LogUtils.getShellShareableInstanceId();
        if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
            switch (launchData.getSplitLaunchType()) {
                case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasks(firstTaskId,
                        optionsBundle, secondTaskId, null /* options2 */, initialStagePosition,
                        DEFAULT_SPLIT_RATIO, remoteTransition, instanceIds.first);
                case SPLIT_SINGLE_INTENT_FULLSCREEN -> mSystemUiProxy.startIntentAndTask(firstPI,
                        firstUserId, optionsBundle, secondTaskId, null /*options2*/,
                        initialStagePosition, DEFAULT_SPLIT_RATIO, remoteTransition,
                        instanceIds.first);
            }
        } else {
            final RemoteAnimationAdapter adapter = getLegacyRemoteAdapter(firstTaskId,
                    secondTaskId, callback);
            switch (launchData.getSplitLaunchType()) {
                case SPLIT_SINGLE_TASK_FULLSCREEN -> mSystemUiProxy.startTasksWithLegacyTransition(
                        firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
                        initialStagePosition, DEFAULT_SPLIT_RATIO, adapter, instanceIds.first);
                case SPLIT_SINGLE_INTENT_FULLSCREEN ->
                        mSystemUiProxy.startIntentAndTaskWithLegacyTransition(firstPI, firstUserId,
                                optionsBundle, secondTaskId, null /*options2*/,
                                initialStagePosition, DEFAULT_SPLIT_RATIO, adapter,
                                instanceIds.first);
            }
        }
    }

    private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId,
            Consumer<Boolean> callback) {
        final RemoteSplitLaunchTransitionRunner animationRunner =
                new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
        return new RemoteTransition(animationRunner,
                ActivityThread.currentActivityThread().getApplicationThread(), "LaunchSplitPair");
    }

    private RemoteAnimationAdapter getLegacyRemoteAdapter(int firstTaskId, int secondTaskId,
            Consumer<Boolean> callback) {
        final RemoteSplitLaunchAnimationRunner animationRunner =
                new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
            final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
                    animationRunner, 300, 150,
        return new RemoteAnimationAdapter(animationRunner, 300, 150,
                ActivityThread.currentActivityThread().getApplicationThread());
            mSystemUiProxy.startTasksWithLegacyTransition(firstTaskId, optionsBundle,
                    secondTaskId, null /* options2 */, stagePosition,
                    splitRatio, adapter, null /*shellInstanceId*/);
        }
    }

    private void launchIntentOrShortcut(Intent intent, UserHandle user, ActivityOptions options1,
+1 −1
Original line number Diff line number Diff line
@@ -3260,7 +3260,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
                true /* isStagedTask */);

        pendingAnimation.addEndListener(animationSuccess ->
                mSplitSelectStateController.launchSplitTasks(launchSuccess ->
                mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess ->
                        resetFromSplitSelectionState()));

        pendingAnimation.buildAnim().start();