Loading libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +56 −52 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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; } } /** /** Loading Loading @@ -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); } } } /** /** Loading @@ -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) { Loading Loading @@ -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(); } } } } Loading @@ -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(); } } Loading @@ -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); } } Loading @@ -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"); } } } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +65 −14 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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); } } libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +108 −5 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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); } } Loading @@ -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); } } Loading @@ -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 Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +60 −13 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +56 −52 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading @@ -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; } } /** /** Loading Loading @@ -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); } } } /** /** Loading @@ -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) { Loading Loading @@ -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(); } } } } Loading @@ -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(); } } Loading @@ -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); } } Loading @@ -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"); } } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +65 −14 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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); } }
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +108 −5 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading @@ -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); } } Loading @@ -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); } } Loading @@ -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 Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +60 −13 File changed.Preview size limit exceeded, changes collapsed. Show changes