Prep work for exposing split-screen APIs to Launcher
Bug: 179176511 Test: DragAndDropPolicyTest Change-Id: Iff8e5df9df87779cf8a33430245fc5584928b33c
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
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.common.ShellExecutor;
|
||||
@@ -155,7 +155,7 @@ public final class ShellCommandHandlerImpl {
|
||||
}
|
||||
final int taskId = new Integer(args[2]);
|
||||
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));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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_RIGHT;
|
||||
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.SIDE_STAGE_POSITION_TOP_OR_LEFT;
|
||||
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
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.ActivityTaskManager;
|
||||
@@ -84,8 +87,7 @@ public class DragAndDropPolicy {
|
||||
private DragSession mSession;
|
||||
|
||||
public DragAndDropPolicy(Context context, SplitScreen splitScreen) {
|
||||
this(context, ActivityTaskManager.getInstance(), splitScreen,
|
||||
new DefaultStarter(context, splitScreen));
|
||||
this(context, ActivityTaskManager.getInstance(), splitScreen, new DefaultStarter(context));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -94,7 +96,7 @@ public class DragAndDropPolicy {
|
||||
mContext = context;
|
||||
mActivityTaskManager = activityTaskManager;
|
||||
mSplitScreen = splitScreen;
|
||||
mStarter = starter;
|
||||
mStarter = mSplitScreen != null ? mSplitScreen : starter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,39 +197,23 @@ public class DragAndDropPolicy {
|
||||
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 leftOrTop = target.type == TYPE_SPLIT_TOP || target.type == TYPE_SPLIT_LEFT;
|
||||
final Bundle opts = dragData.hasExtra(EXTRA_ACTIVITY_OPTIONS)
|
||||
? dragData.getBundleExtra(EXTRA_ACTIVITY_OPTIONS)
|
||||
: new Bundle();
|
||||
|
||||
if (target.type == TYPE_FULLSCREEN) {
|
||||
// Exit split stages if needed
|
||||
mStarter.exitSplitScreen();
|
||||
} else if (mSplitScreen != null) {
|
||||
@SplitScreen.StageType int stage = STAGE_TYPE_UNDEFINED;
|
||||
@SplitScreen.StagePosition int position = STAGE_POSITION_UNDEFINED;
|
||||
if (target.type != TYPE_FULLSCREEN && mSplitScreen != null) {
|
||||
// Update launch options for the split side we are targeting.
|
||||
final int position = leftOrTop
|
||||
? SIDE_STAGE_POSITION_TOP_OR_LEFT : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
position = leftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
if (!inSplitScreen) {
|
||||
// Update the side stage position to match where we want to launch.
|
||||
mSplitScreen.setSideStagePosition(position);
|
||||
// Launch in the side stage if we are not in split-screen already.
|
||||
stage = STAGE_TYPE_SIDE;
|
||||
}
|
||||
mSplitScreen.updateActivityOptions(opts, position);
|
||||
}
|
||||
|
||||
if (isTask) {
|
||||
mStarter.startTask(dragData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID), opts);
|
||||
} else if (isShortcut) {
|
||||
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);
|
||||
}
|
||||
final ClipDescription description = data.getDescription();
|
||||
final Intent dragData = mSession.dragData;
|
||||
mStarter.startClipDescription(description, dragData, stage, position);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -247,7 +233,6 @@ public class DragAndDropPolicy {
|
||||
int runningTaskActType = ACTIVITY_TYPE_STANDARD;
|
||||
boolean runningTaskIsResizeable;
|
||||
boolean dragItemSupportsSplitscreen;
|
||||
boolean isPhone;
|
||||
|
||||
DragSession(Context context, ActivityTaskManager activityTaskManager,
|
||||
DisplayLayout dispLayout, ClipData data) {
|
||||
@@ -275,7 +260,6 @@ public class DragAndDropPolicy {
|
||||
final ActivityInfo info = mInitialDragData.getItemAt(0).getActivityInfo();
|
||||
dragItemSupportsSplitscreen = info == null
|
||||
|| ActivityInfo.isResizeableMode(info.resizeMode);
|
||||
isPhone = mContext.getResources().getConfiguration().smallestScreenWidthDp < 600;
|
||||
dragData = mInitialDragData.getItemAt(0).getIntent();
|
||||
}
|
||||
}
|
||||
@@ -284,11 +268,33 @@ public class DragAndDropPolicy {
|
||||
* Interface for actually committing the task launches.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
interface Starter {
|
||||
void startTask(int taskId, Bundle activityOptions);
|
||||
void startShortcut(String packageName, String shortcutId, Bundle activityOptions,
|
||||
UserHandle user);
|
||||
void startIntent(PendingIntent intent, Bundle activityOptions);
|
||||
public interface Starter {
|
||||
default void startClipDescription(ClipDescription description, Intent intent,
|
||||
@SplitScreen.StageType int stage, @SplitScreen.StagePosition int position) {
|
||||
final boolean isTask = description.hasMimeType(MIMETYPE_APPLICATION_TASK);
|
||||
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 exitSplitScreen();
|
||||
}
|
||||
@@ -299,39 +305,39 @@ public class DragAndDropPolicy {
|
||||
*/
|
||||
private static class DefaultStarter implements Starter {
|
||||
private final Context mContext;
|
||||
private final SplitScreen mSplitScreen;
|
||||
|
||||
public DefaultStarter(Context context, SplitScreen splitScreen) {
|
||||
public DefaultStarter(Context context) {
|
||||
mContext = context;
|
||||
mSplitScreen = splitScreen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTask(int taskId, Bundle activityOptions) {
|
||||
public void startTask(int taskId, int stage, int position,
|
||||
@Nullable Bundle options) {
|
||||
try {
|
||||
ActivityTaskManager.getService().startActivityFromRecents(taskId, activityOptions);
|
||||
ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to launch task", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startShortcut(String packageName, String shortcutId, Bundle activityOptions,
|
||||
UserHandle user) {
|
||||
public void startShortcut(String packageName, String shortcutId, int stage, int position,
|
||||
@Nullable Bundle options, UserHandle user) {
|
||||
try {
|
||||
LauncherApps launcherApps =
|
||||
mContext.getSystemService(LauncherApps.class);
|
||||
launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
|
||||
activityOptions, user);
|
||||
options, user);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Slog.e(TAG, "Failed to launch shortcut", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startIntent(PendingIntent intent, Bundle activityOptions) {
|
||||
public void startIntent(PendingIntent intent, int stage, int position,
|
||||
@Nullable Bundle options) {
|
||||
try {
|
||||
intent.send(null, 0, null, null, null, null, activityOptions);
|
||||
intent.send(null, 0, null, null, null, null, options);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
Slog.e(TAG, "Failed to launch activity", e);
|
||||
}
|
||||
@@ -339,14 +345,12 @@ public class DragAndDropPolicy {
|
||||
|
||||
@Override
|
||||
public void enterSplitScreen(int taskId, boolean leftOrTop) {
|
||||
mSplitScreen.moveToSideStage(taskId,
|
||||
leftOrTop ? SIDE_STAGE_POSITION_TOP_OR_LEFT
|
||||
: SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT);
|
||||
throw new UnsupportedOperationException("enterSplitScreen not implemented by starter");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitSplitScreen() {
|
||||
mSplitScreen.exitSplitScreen();
|
||||
throw new UnsupportedOperationException("exitSplitScreen not implemented by starter");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,16 @@ package com.android.wm.shell.splitscreen;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -31,46 +35,93 @@ import java.io.PrintWriter;
|
||||
* Interface to engage split-screen feature.
|
||||
*/
|
||||
@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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
int SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
|
||||
int STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
|
||||
|
||||
@IntDef(prefix = { "SIDE_STAGE_POSITION_" }, value = {
|
||||
SIDE_STAGE_POSITION_TOP_OR_LEFT,
|
||||
SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT
|
||||
@IntDef(prefix = { "STAGE_POSITION_" }, value = {
|
||||
STAGE_POSITION_UNDEFINED,
|
||||
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. */
|
||||
boolean isSplitScreenVisible();
|
||||
/** 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. */
|
||||
boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
|
||||
@SideStagePosition int sideStagePosition);
|
||||
@StagePosition int sideStagePosition);
|
||||
/** Removes a task from the side-stage of split-screen. */
|
||||
boolean removeFromSideStage(int taskId);
|
||||
/** 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. */
|
||||
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. */
|
||||
void exitSplitScreen();
|
||||
/** Gets the stage bounds. */
|
||||
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. */
|
||||
void dump(@NonNull PrintWriter pw, String prefix);
|
||||
/** Called when the shell organizer has been registered. */
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,19 @@ package com.android.wm.shell.splitscreen;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
@@ -69,7 +77,7 @@ public class SplitScreenController implements SplitScreen {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition) {
|
||||
public boolean moveToSideStage(int taskId, @StagePosition int sideStagePosition) {
|
||||
final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
|
||||
if (task == null) {
|
||||
throw new IllegalArgumentException("Unknown taskId" + taskId);
|
||||
@@ -79,7 +87,7 @@ public class SplitScreenController implements SplitScreen {
|
||||
|
||||
@Override
|
||||
public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
|
||||
@SideStagePosition int sideStagePosition) {
|
||||
@StagePosition int sideStagePosition) {
|
||||
return mStageCoordinator.moveToSideStage(task, sideStagePosition);
|
||||
}
|
||||
|
||||
@@ -89,7 +97,7 @@ public class SplitScreenController implements SplitScreen {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSideStagePosition(@SideStagePosition int sideStagePosition) {
|
||||
public void setSideStagePosition(@StagePosition int sideStagePosition) {
|
||||
mStageCoordinator.setSideStagePosition(sideStagePosition);
|
||||
}
|
||||
|
||||
@@ -109,8 +117,103 @@ public class SplitScreenController implements SplitScreen {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateActivityOptions(Bundle opts, @SideStagePosition int position) {
|
||||
mStageCoordinator.updateActivityOptions(opts, position);
|
||||
public void registerSplitScreenListener(SplitScreenListener listener) {
|
||||
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
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
package com.android.wm.shell.splitscreen;
|
||||
|
||||
import static android.app.ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN;
|
||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||
|
||||
import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_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_BOTTOM_OR_RIGHT;
|
||||
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_TOP_OR_LEFT;
|
||||
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
|
||||
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.content.Context;
|
||||
@@ -41,6 +43,8 @@ import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.common.split.SplitLayout;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and
|
||||
@@ -64,8 +68,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
private final StageListenerImpl mMainStageListener = new StageListenerImpl();
|
||||
private final SideStage mSideStage;
|
||||
private final StageListenerImpl mSideStageListener = new StageListenerImpl();
|
||||
private @SplitScreen.SideStagePosition int mSideStagePosition =
|
||||
SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
private @SplitScreen.StagePosition int mSideStagePosition = STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
|
||||
private final int mDisplayId;
|
||||
private SplitLayout mSplitLayout;
|
||||
@@ -75,6 +78,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
private final ShellTaskOrganizer mTaskOrganizer;
|
||||
private DisplayAreaInfo mDisplayAreaInfo;
|
||||
private final Context mContext;
|
||||
private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
|
||||
|
||||
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
|
||||
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer) {
|
||||
@@ -107,7 +111,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
}
|
||||
|
||||
boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
|
||||
@SplitScreen.SideStagePosition int sideStagePosition) {
|
||||
@SplitScreen.StagePosition int sideStagePosition) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mSideStagePosition = sideStagePosition;
|
||||
mMainStage.activate(getMainStageBounds(), wct);
|
||||
@@ -130,7 +134,16 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
return result;
|
||||
}
|
||||
|
||||
void setSideStagePosition(@SplitScreen.SideStagePosition int sideStagePosition) {
|
||||
@SplitScreen.StagePosition int getSideStagePosition() {
|
||||
return mSideStagePosition;
|
||||
}
|
||||
|
||||
@SplitScreen.StagePosition int getMainStagePosition() {
|
||||
return mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
|
||||
? STAGE_POSITION_BOTTOM_OR_RIGHT : STAGE_POSITION_TOP_OR_LEFT;
|
||||
}
|
||||
|
||||
void setSideStagePosition(@SplitScreen.StagePosition int sideStagePosition) {
|
||||
mSideStagePosition = sideStagePosition;
|
||||
if (mSideStageListener.mVisible) {
|
||||
onStageVisibilityChanged(mSideStageListener);
|
||||
@@ -163,7 +176,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
outBottomOrRightBounds.set(mSplitLayout.getBounds2());
|
||||
}
|
||||
|
||||
void updateActivityOptions(Bundle opts, @SplitScreen.SideStagePosition int position) {
|
||||
void updateActivityOptions(Bundle opts, @SplitScreen.StagePosition int position) {
|
||||
final StageTaskListener stage = position == mSideStagePosition ? mSideStage : mMainStage;
|
||||
opts.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, stage.mRootTaskInfo.token);
|
||||
|
||||
@@ -176,6 +189,35 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
}
|
||||
}
|
||||
|
||||
void registerSplitScreenListener(SplitScreen.SplitScreenListener listener) {
|
||||
if (mListeners.contains(listener)) return;
|
||||
mListeners.add(listener);
|
||||
listener.onStagePositionChanged(STAGE_TYPE_MAIN, getMainStagePosition());
|
||||
listener.onStagePositionChanged(STAGE_TYPE_SIDE, getSideStagePosition());
|
||||
mSideStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_SIDE);
|
||||
mMainStage.onSplitScreenListenerRegistered(listener, STAGE_TYPE_MAIN);
|
||||
}
|
||||
|
||||
void unregisterSplitScreenListener(SplitScreen.SplitScreenListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void onStageChildTaskStatusChanged(
|
||||
StageListenerImpl stageListener, int taskId, boolean present) {
|
||||
|
||||
int stage;
|
||||
if (present) {
|
||||
stage = stageListener == mSideStageListener ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN;
|
||||
} else {
|
||||
// No longer on any stage
|
||||
stage = STAGE_TYPE_UNDEFINED;
|
||||
}
|
||||
|
||||
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||
mListeners.get(i).onTaskStageChanged(taskId, stage);
|
||||
}
|
||||
}
|
||||
|
||||
private void onStageRootTaskAppeared(StageListenerImpl stageListener) {
|
||||
if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
@@ -299,7 +341,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
@Override
|
||||
public void onSnappedToDismiss(boolean bottomOrRight) {
|
||||
final boolean mainStageToTop = bottomOrRight
|
||||
&& mSideStagePosition == SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
&& mSideStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
exitSplitScreen(mainStageToTop ? mMainStage : mSideStage);
|
||||
}
|
||||
|
||||
@@ -326,8 +368,8 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
|
||||
@Override
|
||||
public void onDoubleTappedDivider() {
|
||||
setSideStagePosition(mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT
|
||||
? SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT : SIDE_STAGE_POSITION_TOP_OR_LEFT);
|
||||
setSideStagePosition(mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
|
||||
? STAGE_POSITION_BOTTOM_OR_RIGHT : STAGE_POSITION_TOP_OR_LEFT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -380,12 +422,12 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
}
|
||||
|
||||
private Rect getSideStageBounds() {
|
||||
return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT
|
||||
return mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
|
||||
? mSplitLayout.getBounds1() : mSplitLayout.getBounds2();
|
||||
}
|
||||
|
||||
private Rect getMainStageBounds() {
|
||||
return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT
|
||||
return mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT
|
||||
? mSplitLayout.getBounds2() : mSplitLayout.getBounds1();
|
||||
}
|
||||
|
||||
@@ -428,6 +470,11 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildTaskStatusChanged(int taskId, boolean present) {
|
||||
StageCoordinator.this.onStageChildTaskStatusChanged(this, taskId, present);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRootTaskVanished() {
|
||||
reset();
|
||||
|
||||
@@ -58,6 +58,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
public interface StageListenerCallbacks {
|
||||
void onRootTaskAppeared();
|
||||
void onStatusChanged(boolean visible, boolean hasChildren);
|
||||
void onChildTaskStatusChanged(int taskId, boolean present);
|
||||
void onRootTaskVanished();
|
||||
}
|
||||
private final StageListenerCallbacks mCallbacks;
|
||||
@@ -83,9 +84,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
mRootTaskInfo = taskInfo;
|
||||
mCallbacks.onRootTaskAppeared();
|
||||
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
|
||||
mChildrenLeashes.put(taskInfo.taskId, leash);
|
||||
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
|
||||
final int taskId = taskInfo.taskId;
|
||||
mChildrenLeashes.put(taskId, leash);
|
||||
mChildrenTaskInfo.put(taskId, taskInfo);
|
||||
updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
|
||||
mCallbacks.onChildTaskStatusChanged(taskId, true /* present */);
|
||||
} else {
|
||||
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
|
||||
+ "\n mRootTaskInfo: " + mRootTaskInfo);
|
||||
@@ -120,6 +123,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
mChildrenTaskInfo.remove(taskId);
|
||||
mChildrenLeashes.remove(taskId);
|
||||
sendStatusChanged();
|
||||
mCallbacks.onChildTaskStatusChanged(taskId, false /* present */);
|
||||
} else {
|
||||
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
|
||||
+ "\n mRootTaskInfo: " + mRootTaskInfo);
|
||||
@@ -134,6 +138,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
wct.reorder(mRootTaskInfo.token, visible /* onTop */);
|
||||
}
|
||||
|
||||
void onSplitScreenListenerRegistered(SplitScreen.SplitScreenListener listener,
|
||||
@SplitScreen.StageType int stage) {
|
||||
for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
|
||||
listener.onTaskStageChanged(mChildrenTaskInfo.keyAt(i), stage);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChildTaskSurface(ActivityManager.RunningTaskInfo taskInfo,
|
||||
SurfaceControl leash, boolean firstAppeared) {
|
||||
final Point taskPositionInParent = taskInfo.positionInParent;
|
||||
|
||||
@@ -29,6 +29,10 @@ 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_RIGHT;
|
||||
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP;
|
||||
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_POSITION_BOTTOM_OR_RIGHT;
|
||||
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 static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
@@ -86,11 +90,9 @@ public class DragAndDropPolicyTest {
|
||||
@Mock
|
||||
private ActivityTaskManager mActivityTaskManager;
|
||||
|
||||
// Both the split-screen and start interface.
|
||||
@Mock
|
||||
private SplitScreen mSplitScreen;
|
||||
|
||||
@Mock
|
||||
private DragAndDropPolicy.Starter mStarter;
|
||||
private SplitScreen mSplitScreenStarter;
|
||||
|
||||
private DisplayLayout mLandscapeDisplayLayout;
|
||||
private DisplayLayout mPortraitDisplayLayout;
|
||||
@@ -126,7 +128,7 @@ public class DragAndDropPolicyTest {
|
||||
mInsets = Insets.of(0, 0, 0, 0);
|
||||
|
||||
mPolicy = new DragAndDropPolicy(
|
||||
mContext, mActivityTaskManager, mSplitScreen, mStarter);
|
||||
mContext, mActivityTaskManager, mSplitScreenStarter, mSplitScreenStarter);
|
||||
mActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
|
||||
mNonResizeableActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
|
||||
setClipDataResizeable(mNonResizeableActivityClipData, false);
|
||||
@@ -191,7 +193,7 @@ public class DragAndDropPolicyTest {
|
||||
}
|
||||
|
||||
private void setInSplitScreen(boolean inSplitscreen) {
|
||||
doReturn(inSplitscreen).when(mSplitScreen).isSplitScreenVisible();
|
||||
doReturn(inSplitscreen).when(mSplitScreenStarter).isSplitScreenVisible();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -202,7 +204,8 @@ public class DragAndDropPolicyTest {
|
||||
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -213,12 +216,13 @@ public class DragAndDropPolicyTest {
|
||||
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
|
||||
verify(mStarter).exitSplitScreen();
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
reset(mStarter);
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
|
||||
reset(mSplitScreenStarter);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -229,12 +233,13 @@ public class DragAndDropPolicyTest {
|
||||
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
|
||||
verify(mStarter).exitSplitScreen();
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
reset(mStarter);
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
|
||||
reset(mSplitScreenStarter);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -245,7 +250,8 @@ public class DragAndDropPolicyTest {
|
||||
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -256,7 +262,8 @@ public class DragAndDropPolicyTest {
|
||||
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -268,12 +275,14 @@ public class DragAndDropPolicyTest {
|
||||
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
reset(mStarter);
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
|
||||
reset(mSplitScreenStarter);
|
||||
|
||||
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -285,12 +294,14 @@ public class DragAndDropPolicyTest {
|
||||
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
|
||||
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
reset(mStarter);
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
|
||||
reset(mSplitScreenStarter);
|
||||
|
||||
// TODO(b/169894807): Just verify starting for the non-docked task until we have app pairs
|
||||
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
|
||||
verify(mStarter).startIntent(any(), any());
|
||||
verify(mSplitScreenStarter).startClipDescription(any(), any(),
|
||||
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.android.wm.shell.splitscreen;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
|
||||
|
||||
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 org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -71,7 +71,7 @@ public class StageCoordinatorTests extends ShellTestCase {
|
||||
public void testMoveToSideStage() {
|
||||
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
|
||||
|
||||
mStageCoordinator.moveToSideStage(task, SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT);
|
||||
mStageCoordinator.moveToSideStage(task, STAGE_POSITION_BOTTOM_OR_RIGHT);
|
||||
|
||||
verify(mMainStage).activate(any(Rect.class), any(WindowContainerTransaction.class));
|
||||
verify(mSideStage).addTask(eq(task), any(Rect.class),
|
||||
|
||||
Reference in New Issue
Block a user