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

Commit 70cb47fc authored by Wale Ogunwale's avatar Wale Ogunwale Committed by Automerger Merge Worker
Browse files

Merge "Prep work for exposing split-screen APIs to Launcher" into sc-dev am: 7ae91f9d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13454817

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Ic963b2b6bb5b927e492e574c574aeff0042e0366
parents 75651dac 7ae91f9d
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -16,7 +16,7 @@


package com.android.wm.shell;
package com.android.wm.shell;


import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;


import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.ShellExecutor;
@@ -155,7 +155,7 @@ public final class ShellCommandHandlerImpl {
        }
        }
        final int taskId = new Integer(args[2]);
        final int taskId = new Integer(args[2]);
        final int sideStagePosition = args.length > 3
        final int sideStagePosition = args.length > 3
                ? new Integer(args[3]) : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
                ? new Integer(args[3]) : STAGE_POSITION_BOTTOM_OR_RIGHT;
        mSplitScreenOptional.ifPresent(split -> split.moveToSideStage(taskId, sideStagePosition));
        mSplitScreenOptional.ifPresent(split -> split.moveToSideStage(taskId, sideStagePosition));
        return true;
        return true;
    }
    }
+56 −52
Original line number Original line Diff line number Diff line
@@ -34,8 +34,11 @@ import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPL
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP;
import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;


import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager;
@@ -84,8 +87,7 @@ public class DragAndDropPolicy {
    private DragSession mSession;
    private DragSession mSession;


    public DragAndDropPolicy(Context context, SplitScreen splitScreen) {
    public DragAndDropPolicy(Context context, SplitScreen splitScreen) {
        this(context, ActivityTaskManager.getInstance(), splitScreen,
        this(context, ActivityTaskManager.getInstance(), splitScreen, new DefaultStarter(context));
                new DefaultStarter(context, splitScreen));
    }
    }


    @VisibleForTesting
    @VisibleForTesting
@@ -94,7 +96,7 @@ public class DragAndDropPolicy {
        mContext = context;
        mContext = context;
        mActivityTaskManager = activityTaskManager;
        mActivityTaskManager = activityTaskManager;
        mSplitScreen = splitScreen;
        mSplitScreen = splitScreen;
        mStarter = starter;
        mStarter = mSplitScreen != null ? mSplitScreen : starter;
    }
    }


    /**
    /**
@@ -195,39 +197,23 @@ public class DragAndDropPolicy {
            return;
            return;
        }
        }


        final ClipDescription description = data.getDescription();
        final boolean isTask = description.hasMimeType(MIMETYPE_APPLICATION_TASK);
        final boolean isShortcut = description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT);
        final Intent dragData = mSession.dragData;
        final boolean inSplitScreen = mSplitScreen != null && mSplitScreen.isSplitScreenVisible();
        final boolean inSplitScreen = mSplitScreen != null && mSplitScreen.isSplitScreenVisible();
        final boolean leftOrTop = target.type == TYPE_SPLIT_TOP || target.type == TYPE_SPLIT_LEFT;
        final boolean leftOrTop = target.type == TYPE_SPLIT_TOP || target.type == TYPE_SPLIT_LEFT;
        final Bundle opts = dragData.hasExtra(EXTRA_ACTIVITY_OPTIONS)

                ? dragData.getBundleExtra(EXTRA_ACTIVITY_OPTIONS)
        @SplitScreen.StageType int stage = STAGE_TYPE_UNDEFINED;
                : new Bundle();
        @SplitScreen.StagePosition int position = STAGE_POSITION_UNDEFINED;

        if (target.type != TYPE_FULLSCREEN && mSplitScreen != null) {
        if (target.type == TYPE_FULLSCREEN) {
            // Exit split stages if needed
            mStarter.exitSplitScreen();
        } else if (mSplitScreen != null) {
            // Update launch options for the split side we are targeting.
            // Update launch options for the split side we are targeting.
            final int position = leftOrTop
            position = leftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
                    ? SIDE_STAGE_POSITION_TOP_OR_LEFT : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
            if (!inSplitScreen) {
            if (!inSplitScreen) {
                // Update the side stage position to match where we want to launch.
                // Launch in the side stage if we are not in split-screen already.
                mSplitScreen.setSideStagePosition(position);
                stage = STAGE_TYPE_SIDE;
            }
            }
            mSplitScreen.updateActivityOptions(opts, position);
        }
        }


        if (isTask) {
        final ClipDescription description = data.getDescription();
            mStarter.startTask(dragData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID), opts);
        final Intent dragData = mSession.dragData;
        } else if (isShortcut) {
        mStarter.startClipDescription(description, dragData, stage, position);
            mStarter.startShortcut(dragData.getStringExtra(EXTRA_PACKAGE_NAME),
                    dragData.getStringExtra(EXTRA_SHORTCUT_ID),
                    opts, dragData.getParcelableExtra(EXTRA_USER));
        } else {
            mStarter.startIntent(dragData.getParcelableExtra(EXTRA_PENDING_INTENT), opts);
        }
    }
    }


    /**
    /**
@@ -247,7 +233,6 @@ public class DragAndDropPolicy {
        int runningTaskActType = ACTIVITY_TYPE_STANDARD;
        int runningTaskActType = ACTIVITY_TYPE_STANDARD;
        boolean runningTaskIsResizeable;
        boolean runningTaskIsResizeable;
        boolean dragItemSupportsSplitscreen;
        boolean dragItemSupportsSplitscreen;
        boolean isPhone;


        DragSession(Context context, ActivityTaskManager activityTaskManager,
        DragSession(Context context, ActivityTaskManager activityTaskManager,
                DisplayLayout dispLayout, ClipData data) {
                DisplayLayout dispLayout, ClipData data) {
@@ -275,7 +260,6 @@ public class DragAndDropPolicy {
            final ActivityInfo info = mInitialDragData.getItemAt(0).getActivityInfo();
            final ActivityInfo info = mInitialDragData.getItemAt(0).getActivityInfo();
            dragItemSupportsSplitscreen = info == null
            dragItemSupportsSplitscreen = info == null
                    || ActivityInfo.isResizeableMode(info.resizeMode);
                    || ActivityInfo.isResizeableMode(info.resizeMode);
            isPhone = mContext.getResources().getConfiguration().smallestScreenWidthDp < 600;
            dragData = mInitialDragData.getItemAt(0).getIntent();
            dragData = mInitialDragData.getItemAt(0).getIntent();
        }
        }
    }
    }
@@ -284,11 +268,33 @@ public class DragAndDropPolicy {
     * Interface for actually committing the task launches.
     * Interface for actually committing the task launches.
     */
     */
    @VisibleForTesting
    @VisibleForTesting
    interface Starter {
    public interface Starter {
        void startTask(int taskId, Bundle activityOptions);
        default void startClipDescription(ClipDescription description, Intent intent,
        void startShortcut(String packageName, String shortcutId, Bundle activityOptions,
                @SplitScreen.StageType int stage, @SplitScreen.StagePosition int position) {
                UserHandle user);
            final boolean isTask = description.hasMimeType(MIMETYPE_APPLICATION_TASK);
        void startIntent(PendingIntent intent, Bundle activityOptions);
            final boolean isShortcut = description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT);
            final Bundle opts = intent.hasExtra(EXTRA_ACTIVITY_OPTIONS)
                    ? intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS) : new Bundle();

            if (isTask) {
                final int taskId = intent.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID);
                startTask(taskId, stage, position, opts);
            } else if (isShortcut) {
                final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
                final String id = intent.getStringExtra(EXTRA_SHORTCUT_ID);
                final UserHandle user = intent.getParcelableExtra(EXTRA_USER);
                startShortcut(packageName, id, stage, position, opts, user);
            } else {
                startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT), stage, position, opts);
            }
        }
        void startTask(int taskId, @SplitScreen.StageType int stage,
                @SplitScreen.StagePosition int position, @Nullable Bundle options);
        void startShortcut(String packageName, String shortcutId,
                @SplitScreen.StageType int stage, @SplitScreen.StagePosition int position,
                @Nullable Bundle options, UserHandle user);
        void startIntent(PendingIntent intent, @SplitScreen.StageType int stage,
                @SplitScreen.StagePosition int position, @Nullable Bundle options);
        void enterSplitScreen(int taskId, boolean leftOrTop);
        void enterSplitScreen(int taskId, boolean leftOrTop);
        void exitSplitScreen();
        void exitSplitScreen();
    }
    }
@@ -299,39 +305,39 @@ public class DragAndDropPolicy {
     */
     */
    private static class DefaultStarter implements Starter {
    private static class DefaultStarter implements Starter {
        private final Context mContext;
        private final Context mContext;
        private final SplitScreen mSplitScreen;


        public DefaultStarter(Context context, SplitScreen splitScreen) {
        public DefaultStarter(Context context) {
            mContext = context;
            mContext = context;
            mSplitScreen = splitScreen;
        }
        }


        @Override
        @Override
        public void startTask(int taskId, Bundle activityOptions) {
        public void startTask(int taskId, int stage, int position,
                @Nullable Bundle options) {
            try {
            try {
                ActivityTaskManager.getService().startActivityFromRecents(taskId, activityOptions);
                ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
            } catch (RemoteException e) {
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to launch task", e);
                Slog.e(TAG, "Failed to launch task", e);
            }
            }
        }
        }


        @Override
        @Override
        public void startShortcut(String packageName, String shortcutId, Bundle activityOptions,
        public void startShortcut(String packageName, String shortcutId, int stage, int position,
                UserHandle user) {
                @Nullable Bundle options, UserHandle user) {
            try {
            try {
                LauncherApps launcherApps =
                LauncherApps launcherApps =
                        mContext.getSystemService(LauncherApps.class);
                        mContext.getSystemService(LauncherApps.class);
                launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
                launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
                        activityOptions, user);
                        options, user);
            } catch (ActivityNotFoundException e) {
            } catch (ActivityNotFoundException e) {
                Slog.e(TAG, "Failed to launch shortcut", e);
                Slog.e(TAG, "Failed to launch shortcut", e);
            }
            }
        }
        }


        @Override
        @Override
        public void startIntent(PendingIntent intent, Bundle activityOptions) {
        public void startIntent(PendingIntent intent, int stage, int position,
                @Nullable Bundle options) {
            try {
            try {
                intent.send(null, 0, null, null, null, null, activityOptions);
                intent.send(null, 0, null, null, null, null, options);
            } catch (PendingIntent.CanceledException e) {
            } catch (PendingIntent.CanceledException e) {
                Slog.e(TAG, "Failed to launch activity", e);
                Slog.e(TAG, "Failed to launch activity", e);
            }
            }
@@ -339,14 +345,12 @@ public class DragAndDropPolicy {


        @Override
        @Override
        public void enterSplitScreen(int taskId, boolean leftOrTop) {
        public void enterSplitScreen(int taskId, boolean leftOrTop) {
            mSplitScreen.moveToSideStage(taskId,
            throw new UnsupportedOperationException("enterSplitScreen not implemented by starter");
                    leftOrTop ? SIDE_STAGE_POSITION_TOP_OR_LEFT
                            : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT);
        }
        }


        @Override
        @Override
        public void exitSplitScreen() {
        public void exitSplitScreen() {
            mSplitScreen.exitSplitScreen();
            throw new UnsupportedOperationException("exitSplitScreen not implemented by starter");
        }
        }
    }
    }


+65 −14
Original line number Original line Diff line number Diff line
@@ -18,12 +18,16 @@ package com.android.wm.shell.splitscreen;


import android.annotation.IntDef;
import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Bundle;
import android.os.UserHandle;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;


import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;


import java.io.PrintWriter;
import java.io.PrintWriter;


@@ -31,46 +35,93 @@ import java.io.PrintWriter;
 * Interface to engage split-screen feature.
 * Interface to engage split-screen feature.
 */
 */
@ExternalThread
@ExternalThread
public interface SplitScreen {
public interface SplitScreen extends DragAndDropPolicy.Starter {
    /**
    /**
     * Specifies that the side-stage is positioned at the top half of the screen if
     * Stage position isn't specified normally meaning to use what ever it is currently set to.
     */
    int STAGE_POSITION_UNDEFINED = -1;
    /**
     * Specifies that a stage is positioned at the top half of the screen if
     * in portrait mode or at the left half of the screen if in landscape mode.
     * in portrait mode or at the left half of the screen if in landscape mode.
     */
     */
    int SIDE_STAGE_POSITION_TOP_OR_LEFT = 0;
    int STAGE_POSITION_TOP_OR_LEFT = 0;


    /**
    /**
     * Specifies that the side-stage is positioned at the bottom half of the screen if
     * Specifies that a stage is positioned at the bottom half of the screen if
     * in portrait mode or at the right half of the screen if in landscape mode.
     * in portrait mode or at the right half of the screen if in landscape mode.
     */
     */
    int SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
    int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;


    @IntDef(prefix = { "SIDE_STAGE_POSITION_" }, value = {
    @IntDef(prefix = { "STAGE_POSITION_" }, value = {
            SIDE_STAGE_POSITION_TOP_OR_LEFT,
            STAGE_POSITION_UNDEFINED,
            SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT
            STAGE_POSITION_TOP_OR_LEFT,
            STAGE_POSITION_BOTTOM_OR_RIGHT
    })
    })
    @interface SideStagePosition {}
    @interface StagePosition {}

    /**
     * Stage type isn't specified normally meaning to use what ever the default is.
     * E.g. exit split-screen and launch the app in fullscreen.
     */
    int STAGE_TYPE_UNDEFINED = -1;
    /**
     * The main stage type.
     * @see MainStage
     */
    int STAGE_TYPE_MAIN = 0;

    /**
     * The side stage type.
     * @see SideStage
     */
    int STAGE_TYPE_SIDE = 1;

    @IntDef(prefix = { "STAGE_TYPE_" }, value = {
            STAGE_TYPE_UNDEFINED,
            STAGE_TYPE_MAIN,
            STAGE_TYPE_SIDE
    })
    @interface StageType {}

    /** Callback interface for listening to changes in a split-screen stage. */
    interface SplitScreenListener {
        void onStagePositionChanged(@StageType int stage, @StagePosition int position);
        void onTaskStageChanged(int taskId, @StageType int stage);
    }


    /** @return {@code true} if split-screen is currently visible. */
    /** @return {@code true} if split-screen is currently visible. */
    boolean isSplitScreenVisible();
    boolean isSplitScreenVisible();
    /** Moves a task in the side-stage of split-screen. */
    /** Moves a task in the side-stage of split-screen. */
    boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition);
    boolean moveToSideStage(int taskId, @StagePosition int sideStagePosition);
    /** Moves a task in the side-stage of split-screen. */
    /** Moves a task in the side-stage of split-screen. */
    boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
    boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
            @SideStagePosition int sideStagePosition);
            @StagePosition int sideStagePosition);
    /** Removes a task from the side-stage of split-screen. */
    /** Removes a task from the side-stage of split-screen. */
    boolean removeFromSideStage(int taskId);
    boolean removeFromSideStage(int taskId);
    /** Sets the position of the side-stage. */
    /** Sets the position of the side-stage. */
    void setSideStagePosition(@SideStagePosition int sideStagePosition);
    void setSideStagePosition(@StagePosition int sideStagePosition);
    /** Hides the side-stage if it is currently visible. */
    /** Hides the side-stage if it is currently visible. */
    void setSideStageVisibility(boolean visible);
    void setSideStageVisibility(boolean visible);
    default void enterSplitScreen(int taskId, boolean leftOrTop) {
        moveToSideStage(taskId,
                leftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT);
    }
    /** Removes the split-screen stages. */
    /** Removes the split-screen stages. */
    void exitSplitScreen();
    void exitSplitScreen();
    /** Gets the stage bounds. */
    /** Gets the stage bounds. */
    void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds);
    void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds);
    /** Updates the launch activity options for the split position we want to launch it in. */
    void updateActivityOptions(Bundle opts, @SideStagePosition int position);
    /** Dumps current status of split-screen. */
    /** Dumps current status of split-screen. */
    void dump(@NonNull PrintWriter pw, String prefix);
    void dump(@NonNull PrintWriter pw, String prefix);
    /** Called when the shell organizer has been registered. */
    /** Called when the shell organizer has been registered. */
    void onOrganizerRegistered();
    void onOrganizerRegistered();

    void registerSplitScreenListener(SplitScreenListener listener);
    void unregisterSplitScreenListener(SplitScreenListener listener);

    void startTask(int taskId,
            @StageType int stage, @StagePosition int position, @Nullable Bundle options);
    void startShortcut(String packageName, String shortcutId, @StageType int stage,
            @StagePosition int position, @Nullable Bundle options, UserHandle user);
    void startIntent(PendingIntent intent,
            @StageType int stage, @StagePosition int position, @Nullable Bundle options);
}
}
+108 −5
Original line number Original line Diff line number Diff line
@@ -19,11 +19,19 @@ package com.android.wm.shell.splitscreen;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;


import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Context;
import android.content.pm.LauncherApps;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;


import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -69,7 +77,7 @@ public class SplitScreenController implements SplitScreen {
    }
    }


    @Override
    @Override
    public boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition) {
    public boolean moveToSideStage(int taskId, @StagePosition int sideStagePosition) {
        final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
        final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
        if (task == null) {
        if (task == null) {
            throw new IllegalArgumentException("Unknown taskId" + taskId);
            throw new IllegalArgumentException("Unknown taskId" + taskId);
@@ -79,7 +87,7 @@ public class SplitScreenController implements SplitScreen {


    @Override
    @Override
    public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
    public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
            @SideStagePosition int sideStagePosition) {
            @StagePosition int sideStagePosition) {
        return mStageCoordinator.moveToSideStage(task, sideStagePosition);
        return mStageCoordinator.moveToSideStage(task, sideStagePosition);
    }
    }


@@ -89,7 +97,7 @@ public class SplitScreenController implements SplitScreen {
    }
    }


    @Override
    @Override
    public void setSideStagePosition(@SideStagePosition int sideStagePosition) {
    public void setSideStagePosition(@StagePosition int sideStagePosition) {
        mStageCoordinator.setSideStagePosition(sideStagePosition);
        mStageCoordinator.setSideStagePosition(sideStagePosition);
    }
    }


@@ -109,8 +117,103 @@ public class SplitScreenController implements SplitScreen {
    }
    }


    @Override
    @Override
    public void updateActivityOptions(Bundle opts, @SideStagePosition int position) {
    public void registerSplitScreenListener(SplitScreenListener listener) {
        mStageCoordinator.updateActivityOptions(opts, position);
        mStageCoordinator.registerSplitScreenListener(listener);
    }

    @Override
    public void unregisterSplitScreenListener(SplitScreenListener listener) {
        mStageCoordinator.unregisterSplitScreenListener(listener);
    }

    @Override
    public void startTask(int taskId,
            @StageType int stage, @StagePosition int position, @Nullable Bundle options) {
        options = resolveStartStage(stage, position, options);

        try {
            ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to launch task", e);
        }
    }

    @Override
    public void startShortcut(String packageName, String shortcutId, @StageType int stage,
            @StagePosition int position, @Nullable Bundle options, UserHandle user) {
        options = resolveStartStage(stage, position, options);

        try {
            LauncherApps launcherApps =
                    mContext.getSystemService(LauncherApps.class);
            launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
                    options, user);
        } catch (ActivityNotFoundException e) {
            Slog.e(TAG, "Failed to launch shortcut", e);
        }
    }

    @Override
    public void startIntent(PendingIntent intent,
            @StageType int stage, @StagePosition int position, @Nullable Bundle options) {
        options = resolveStartStage(stage, position, options);

        try {
            intent.send(null, 0, null, null, null, null, options);
        } catch (PendingIntent.CanceledException e) {
            Slog.e(TAG, "Failed to launch activity", e);
        }
    }

    private Bundle resolveStartStage(@StageType int stage, @StagePosition int position,
            @Nullable Bundle options) {
        switch (stage) {
            case STAGE_TYPE_UNDEFINED: {
                // Use the stage of the specified position is valid.
                if (position != STAGE_POSITION_UNDEFINED) {
                    if (position == mStageCoordinator.getSideStagePosition()) {
                        options = resolveStartStage(STAGE_TYPE_SIDE, position, options);
                    } else {
                        options = resolveStartStage(STAGE_TYPE_MAIN, position, options);
                    }
                } else {
                    // Exit split-screen and launch fullscreen since stage wasn't specified.
                    mStageCoordinator.exitSplitScreen();
                }
                break;
            }
            case STAGE_TYPE_SIDE: {
                if (position != STAGE_POSITION_UNDEFINED) {
                    mStageCoordinator.setSideStagePosition(position);
                } else {
                    position = mStageCoordinator.getSideStagePosition();
                }
                if (options == null) {
                    options = new Bundle();
                }
                mStageCoordinator.updateActivityOptions(options, position);
                break;
            }
            case STAGE_TYPE_MAIN: {
                if (position != STAGE_POSITION_UNDEFINED) {
                    // Set the side stage opposite of what we want to the main stage.
                    final int sideStagePosition = position == STAGE_POSITION_TOP_OR_LEFT
                            ? STAGE_POSITION_BOTTOM_OR_RIGHT : STAGE_POSITION_TOP_OR_LEFT;
                    mStageCoordinator.setSideStagePosition(sideStagePosition);
                } else {
                    position = mStageCoordinator.getMainStagePosition();
                }
                if (options == null) {
                    options = new Bundle();
                }
                mStageCoordinator.updateActivityOptions(options, position);
                break;
            }
            default:
                throw new IllegalArgumentException("Unknown stage=" + stage);
        }

        return options;
    }
    }


    @Override
    @Override
+60 −13

File changed.

Preview size limit exceeded, changes collapsed.

Loading