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

Commit 063521fe authored by Vinit Nayak's avatar Vinit Nayak
Browse files

Allow consuming another intent for widgets to launch in split

* Bundle2 in startIntents() and startIntentAndTask() will now
check for the presence of a widgetIntent. Sometimes widgets
send both a pendingIntent as well as a regular intent and both
of these may be necessary to resolve their app to launch

Bug: 311263727
Test: Tested w/ 2 fresh launches, app + widget.
Also with existing task + widget.
Was not able to accurately test multiple tasks launched by the
widget since there are some issues with the allowlist check.
And the working case for multiple instances of Chrome didn't
work because none of the chrome widgets rely on the secondary
intent to launch any of the app's activities
Flag: None, technically this code isn't reachable since widgets
are unsupported, but didn't seem worthwhile to add a separate flag
in the short duration we will begin supporting them again

Change-Id: I6ecd4a7cc9e5eb8c7ca928dc066d8c67b71f8227
parent 821d03e8
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -26,11 +26,12 @@ import android.annotation.IntDef;

/** Helper utility class of methods and constants that are available to be imported in Launcher. */
public class SplitScreenConstants {
    /**
     * Duration used for every split fade-in or fade-out.
     */
    /** Duration used for every split fade-in or fade-out. */
    public static final int FADE_DURATION = 133;

    /** Key for passing in widget intents when invoking split from launcher workspace. */
    public static final String KEY_EXTRA_WIDGET_INTENT = "key_extra_widget_intent";

    ///////////////
    // IMPORTANT for the following SPLIT_POSITION and SNAP_TO constants:
    // These int values must not be changed -- they are persisted to user-defined app pairs, and
+41 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;

import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.common.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
@@ -711,10 +712,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        //       recents that hasn't launched and is not being organized
        final String packageName2 = SplitScreenUtils.getPackageName(taskId, mTaskOrganizer);
        final int userId2 = SplitScreenUtils.getUserId(taskId, mTaskOrganizer);
        boolean setSecondIntentMultipleTask = false;
        if (samePackage(packageName1, packageName2, userId1, userId2)) {
            if (supportMultiInstancesSplit(packageName1)) {
                fillInIntent = new Intent();
                fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
                setSecondIntentMultipleTask = true;
                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
            } else {
                if (mRecentTasksOptional.isPresent()) {
@@ -729,6 +730,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                        Toast.LENGTH_SHORT).show();
            }
        }
        if (options2 != null) {
            Intent widgetIntent = options2.getParcelable(KEY_EXTRA_WIDGET_INTENT, Intent.class);
            fillInIntent = resolveWidgetFillinIntent(widgetIntent, setSecondIntentMultipleTask);
        }
        mStageCoordinator.startIntentAndTask(pendingIntent, fillInIntent, options1, taskId,
                options2, splitPosition, snapPosition, remoteTransition, instanceId);
    }
@@ -779,12 +784,12 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                ? ActivityOptions.fromBundle(options1) : ActivityOptions.makeBasic();
        final ActivityOptions activityOptions2 = options2 != null
                ? ActivityOptions.fromBundle(options2) : ActivityOptions.makeBasic();
        boolean setSecondIntentMultipleTask = false;
        if (samePackage(packageName1, packageName2, userId1, userId2)) {
            if (supportMultiInstancesSplit(packageName1)) {
                fillInIntent1 = new Intent();
                fillInIntent1.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
                fillInIntent2 = new Intent();
                fillInIntent2.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
                setSecondIntentMultipleTask = true;

                if (shortcutInfo1 != null) {
                    activityOptions1.setApplyMultipleTaskFlagForShortcut(true);
@@ -803,6 +808,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                        Toast.LENGTH_SHORT).show();
            }
        }
        if (options2 != null) {
            Intent widgetIntent = options2.getParcelable(KEY_EXTRA_WIDGET_INTENT, Intent.class);
            fillInIntent2 = resolveWidgetFillinIntent(widgetIntent, setSecondIntentMultipleTask);
        }
        mStageCoordinator.startIntents(pendingIntent1, fillInIntent1, shortcutInfo1,
                activityOptions1.toBundle(), pendingIntent2, fillInIntent2, shortcutInfo2,
                activityOptions2.toBundle(), splitPosition, snapPosition, remoteTransition,
@@ -908,6 +917,34 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        return false;
    }

    /**
     * Determines whether the widgetIntent needs to be modified if multiple tasks of its
     * corresponding package/app are supported. There are 4 possible paths:
     *  <li> We select a widget for second app which is the same as the first app </li>
     *  <li> We select a widget for second app which is different from the first app </li>
     *  <li> No widgets involved, we select a second app that is the same as first app </li>
     *  <li> No widgets involved, we select a second app that is different from the first app
     *       (returns null) </li>
     *
     * @return an {@link Intent} with the appropriate {@link Intent#FLAG_ACTIVITY_MULTIPLE_TASK}
     *         added on or not depending on {@param launchMultipleTasks}.
     */
    @Nullable
    private Intent resolveWidgetFillinIntent(@Nullable Intent widgetIntent,
            boolean launchMultipleTasks) {
        Intent fillInIntent2 = null;
        if (launchMultipleTasks && widgetIntent != null) {
            fillInIntent2 = widgetIntent;
            fillInIntent2.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
        } else if (widgetIntent != null) {
            fillInIntent2 = widgetIntent;
        } else if (launchMultipleTasks) {
            fillInIntent2 = new Intent();
            fillInIntent2.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
        }
        return fillInIntent2;
    }

    RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) {
        if (ENABLE_SHELL_TRANSITIONS) return null;