10/ Update split for shell thread

- Also remove usages of external interface within the shell code
  and remove methods only used in the controller from the interface
  (will update for other components separately)

Bug: 161979899
Test: atest WMShellUnitTests
Test: atest SystemUITests
Change-Id: I06d266095d8e287ba131e41dc6bebefa15c9e477
This commit is contained in:
Winson Chung
2021-02-05 00:28:15 -08:00
parent 6c75e58fc6
commit 0054d7fc8c
9 changed files with 241 additions and 114 deletions

View File

@@ -25,6 +25,7 @@ import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import java.io.PrintWriter;
import java.util.Optional;
@@ -38,7 +39,7 @@ public final class ShellCommandHandlerImpl {
private static final String TAG = ShellCommandHandlerImpl.class.getSimpleName();
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<SplitScreenController> mSplitScreenOptional;
private final Optional<Pip> mPipOptional;
private final Optional<OneHanded> mOneHandedOptional;
private final Optional<HideDisplayCutout> mHideDisplayCutout;
@@ -50,7 +51,7 @@ public final class ShellCommandHandlerImpl {
public static ShellCommandHandler create(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
@@ -64,7 +65,7 @@ public final class ShellCommandHandlerImpl {
private ShellCommandHandlerImpl(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,

View File

@@ -25,6 +25,7 @@ import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -39,7 +40,7 @@ public class ShellInitImpl {
private final DragAndDropController mDragAndDropController;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<SplitScreenController> mSplitScreenOptional;
private final Optional<AppPairs> mAppPairsOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
private final ShellExecutor mMainExecutor;
@@ -51,7 +52,7 @@ public class ShellInitImpl {
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
@@ -71,7 +72,7 @@ public class ShellInitImpl {
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
@@ -97,7 +98,7 @@ public class ShellInitImpl {
mShellTaskOrganizer.registerOrganizer();
mAppPairsOptional.ifPresent(AppPairs::onOrganizerRegistered);
mSplitScreenOptional.ifPresent(SplitScreen::onOrganizerRegistered);
mSplitScreenOptional.ifPresent(SplitScreenController::onOrganizerRegistered);
// Bind the splitscreen impl to the drag drop controller
mDragAndDropController.initialize(mSplitScreenOptional);

View File

@@ -53,6 +53,7 @@ import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.Optional;
@@ -66,7 +67,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
private final Context mContext;
private final DisplayController mDisplayController;
private SplitScreen mSplitScreen;
private SplitScreenController mSplitScreen;
private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>();
private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
@@ -76,7 +77,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
mDisplayController = displayController;
}
public void initialize(Optional<SplitScreen> splitscreen) {
public void initialize(Optional<SplitScreenController> splitscreen) {
mSplitScreen = splitscreen.orElse(null);
mDisplayController.addDisplayWindowListener(this);
}

View File

@@ -64,7 +64,9 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreen.StagePosition;
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
import com.android.wm.shell.splitscreen.SplitScreenController;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -81,18 +83,18 @@ public class DragAndDropPolicy {
private final Context mContext;
private final ActivityTaskManager mActivityTaskManager;
private final Starter mStarter;
private final SplitScreen mSplitScreen;
private final SplitScreenController mSplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
private DragSession mSession;
public DragAndDropPolicy(Context context, SplitScreen splitScreen) {
public DragAndDropPolicy(Context context, SplitScreenController splitScreen) {
this(context, ActivityTaskManager.getInstance(), splitScreen, new DefaultStarter(context));
}
@VisibleForTesting
DragAndDropPolicy(Context context, ActivityTaskManager activityTaskManager,
SplitScreen splitScreen, Starter starter) {
SplitScreenController splitScreen, Starter starter) {
mContext = context;
mActivityTaskManager = activityTaskManager;
mSplitScreen = splitScreen;
@@ -200,8 +202,8 @@ public class DragAndDropPolicy {
final boolean inSplitScreen = mSplitScreen != null && mSplitScreen.isSplitScreenVisible();
final boolean leftOrTop = target.type == TYPE_SPLIT_TOP || target.type == TYPE_SPLIT_LEFT;
@SplitScreen.StageType int stage = STAGE_TYPE_UNDEFINED;
@SplitScreen.StagePosition int position = STAGE_POSITION_UNDEFINED;
@StageType int stage = STAGE_TYPE_UNDEFINED;
@StagePosition int position = STAGE_POSITION_UNDEFINED;
if (target.type != TYPE_FULLSCREEN && mSplitScreen != null) {
// Update launch options for the split side we are targeting.
position = leftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -213,7 +215,28 @@ public class DragAndDropPolicy {
final ClipDescription description = data.getDescription();
final Intent dragData = mSession.dragData;
mStarter.startClipDescription(description, dragData, stage, position);
startClipDescription(description, dragData, stage, position);
}
private void startClipDescription(ClipDescription description, Intent intent,
@StageType int stage, @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);
mStarter.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);
mStarter.startShortcut(packageName, id, stage, position, opts, user);
} else {
mStarter.startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT), stage, position,
opts);
}
}
/**
@@ -267,34 +290,13 @@ public class DragAndDropPolicy {
/**
* Interface for actually committing the task launches.
*/
@VisibleForTesting
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 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);
void enterSplitScreen(int taskId, boolean leftOrTop);
void exitSplitScreen();
}

View File

@@ -42,7 +42,7 @@ import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import java.util.ArrayList;
@@ -61,7 +61,7 @@ public class DragLayout extends View {
private boolean mIsShowing;
private boolean mHasDropped;
public DragLayout(Context context, SplitScreen splitscreen) {
public DragLayout(Context context, SplitScreenController splitscreen) {
super(context);
mPolicy = new DragAndDropPolicy(context, splitscreen);
mDisplayMargin = context.getResources().getDimensionPixelSize(

View File

@@ -33,6 +33,7 @@ import java.io.PrintWriter;
/**
* Interface to engage split-screen feature.
* TODO: Figure out which of these are actually needed outside of the Shell
*/
@ExternalThread
public interface SplitScreen extends DragAndDropPolicy.Starter {
@@ -102,18 +103,11 @@ public interface SplitScreen extends DragAndDropPolicy.Starter {
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);
/** 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);

View File

@@ -18,6 +18,13 @@ package com.android.wm.shell.splitscreen;
import static android.view.Display.DEFAULT_DISPLAY;
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_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.app.ActivityTaskManager;
import android.app.PendingIntent;
@@ -35,7 +42,9 @@ import androidx.annotation.Nullable;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import java.io.PrintWriter;
@@ -44,25 +53,33 @@ import java.io.PrintWriter;
* {@link SplitScreen}.
* @see StageCoordinator
*/
public class SplitScreenController implements SplitScreen {
public class SplitScreenController implements DragAndDropPolicy.Starter {
private static final String TAG = SplitScreenController.class.getSimpleName();
private final ShellTaskOrganizer mTaskOrganizer;
private final SyncTransactionQueue mSyncQueue;
private final Context mContext;
private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
private final ShellExecutor mMainExecutor;
private final SplitScreenImpl mImpl = new SplitScreenImpl();
private StageCoordinator mStageCoordinator;
public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, Context context,
RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
RootTaskDisplayAreaOrganizer rootTDAOrganizer,
ShellExecutor mainExecutor) {
mTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue;
mContext = context;
mRootTDAOrganizer = rootTDAOrganizer;
mMainExecutor = mainExecutor;
}
public SplitScreen asSplitScreen() {
return mImpl;
}
@Override
public void onOrganizerRegistered() {
if (mStageCoordinator == null) {
// TODO: Multi-display
@@ -71,13 +88,11 @@ public class SplitScreenController implements SplitScreen {
}
}
@Override
public boolean isSplitScreenVisible() {
return mStageCoordinator.isSplitScreenVisible();
}
@Override
public boolean moveToSideStage(int taskId, @StagePosition int sideStagePosition) {
public boolean moveToSideStage(int taskId, @SplitScreen.StagePosition int sideStagePosition) {
final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
if (task == null) {
throw new IllegalArgumentException("Unknown taskId" + taskId);
@@ -85,50 +100,46 @@ public class SplitScreenController implements SplitScreen {
return moveToSideStage(task, sideStagePosition);
}
@Override
public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
@StagePosition int sideStagePosition) {
@SplitScreen.StagePosition int sideStagePosition) {
return mStageCoordinator.moveToSideStage(task, sideStagePosition);
}
@Override
public boolean removeFromSideStage(int taskId) {
return mStageCoordinator.removeFromSideStage(taskId);
}
@Override
public void setSideStagePosition(@StagePosition int sideStagePosition) {
public void setSideStagePosition(@SplitScreen.StagePosition int sideStagePosition) {
mStageCoordinator.setSideStagePosition(sideStagePosition);
}
@Override
public void setSideStageVisibility(boolean visible) {
mStageCoordinator.setSideStageVisibility(visible);
}
@Override
public void enterSplitScreen(int taskId, boolean leftOrTop) {
moveToSideStage(taskId,
leftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT);
}
public void exitSplitScreen() {
mStageCoordinator.exitSplitScreen();
}
@Override
public void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
mStageCoordinator.getStageBounds(outTopOrLeftBounds, outBottomOrRightBounds);
}
@Override
public void registerSplitScreenListener(SplitScreenListener listener) {
public void registerSplitScreenListener(SplitScreen.SplitScreenListener listener) {
mStageCoordinator.registerSplitScreenListener(listener);
}
@Override
public void unregisterSplitScreenListener(SplitScreenListener listener) {
public void unregisterSplitScreenListener(SplitScreen.SplitScreenListener listener) {
mStageCoordinator.unregisterSplitScreenListener(listener);
}
@Override
public void startTask(int taskId,
@StageType int stage, @StagePosition int position, @Nullable Bundle options) {
public void startTask(int taskId, @SplitScreen.StageType int stage,
@SplitScreen.StagePosition int position, @Nullable Bundle options) {
options = resolveStartStage(stage, position, options);
try {
@@ -138,9 +149,9 @@ public class SplitScreenController implements SplitScreen {
}
}
@Override
public void startShortcut(String packageName, String shortcutId, @StageType int stage,
@StagePosition int position, @Nullable Bundle options, UserHandle user) {
public void startShortcut(String packageName, String shortcutId,
@SplitScreen.StageType int stage, @SplitScreen.StagePosition int position,
@Nullable Bundle options, UserHandle user) {
options = resolveStartStage(stage, position, options);
try {
@@ -153,9 +164,8 @@ public class SplitScreenController implements SplitScreen {
}
}
@Override
public void startIntent(PendingIntent intent,
@StageType int stage, @StagePosition int position, @Nullable Bundle options) {
public void startIntent(PendingIntent intent, @SplitScreen.StageType int stage,
@SplitScreen.StagePosition int position, @Nullable Bundle options) {
options = resolveStartStage(stage, position, options);
try {
@@ -165,8 +175,8 @@ public class SplitScreenController implements SplitScreen {
}
}
private Bundle resolveStartStage(@StageType int stage, @StagePosition int position,
@Nullable Bundle options) {
private Bundle resolveStartStage(@SplitScreen.StageType int stage,
@SplitScreen.StagePosition int position, @Nullable Bundle options) {
switch (stage) {
case STAGE_TYPE_UNDEFINED: {
// Use the stage of the specified position is valid.
@@ -216,7 +226,6 @@ public class SplitScreenController implements SplitScreen {
return options;
}
@Override
public void dump(@NonNull PrintWriter pw, String prefix) {
pw.println(prefix + TAG);
if (mStageCoordinator != null) {
@@ -224,4 +233,113 @@ public class SplitScreenController implements SplitScreen {
}
}
private class SplitScreenImpl implements SplitScreen {
@Override
public boolean isSplitScreenVisible() {
return mMainExecutor.executeBlockingForResult(() -> {
return SplitScreenController.this.isSplitScreenVisible();
}, Boolean.class);
}
@Override
public boolean moveToSideStage(int taskId, int sideStagePosition) {
return mMainExecutor.executeBlockingForResult(() -> {
return SplitScreenController.this.moveToSideStage(taskId, sideStagePosition);
}, Boolean.class);
}
@Override
public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
int sideStagePosition) {
return mMainExecutor.executeBlockingForResult(() -> {
return SplitScreenController.this.moveToSideStage(task, sideStagePosition);
}, Boolean.class);
}
@Override
public boolean removeFromSideStage(int taskId) {
return mMainExecutor.executeBlockingForResult(() -> {
return SplitScreenController.this.removeFromSideStage(taskId);
}, Boolean.class);
}
@Override
public void setSideStagePosition(int sideStagePosition) {
mMainExecutor.execute(() -> {
SplitScreenController.this.setSideStagePosition(sideStagePosition);
});
}
@Override
public void setSideStageVisibility(boolean visible) {
mMainExecutor.execute(() -> {
SplitScreenController.this.setSideStageVisibility(visible);
});
}
@Override
public void enterSplitScreen(int taskId, boolean leftOrTop) {
mMainExecutor.execute(() -> {
SplitScreenController.this.enterSplitScreen(taskId, leftOrTop);
});
}
@Override
public void exitSplitScreen() {
mMainExecutor.execute(() -> {
SplitScreenController.this.exitSplitScreen();
});
}
@Override
public void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
try {
mMainExecutor.executeBlocking(() -> {
SplitScreenController.this.getStageBounds(outTopOrLeftBounds,
outBottomOrRightBounds);
});
} catch (InterruptedException e) {
Slog.e(TAG, "Failed to get stage bounds in 2s");
}
}
@Override
public void registerSplitScreenListener(SplitScreenListener listener) {
mMainExecutor.execute(() -> {
SplitScreenController.this.registerSplitScreenListener(listener);
});
}
@Override
public void unregisterSplitScreenListener(SplitScreenListener listener) {
mMainExecutor.execute(() -> {
SplitScreenController.this.unregisterSplitScreenListener(listener);
});
}
@Override
public void startTask(int taskId, int stage, int position, @Nullable Bundle options) {
mMainExecutor.execute(() -> {
SplitScreenController.this.startTask(taskId, stage, position, options);
});
}
@Override
public void startShortcut(String packageName, String shortcutId, int stage, int position,
@Nullable Bundle options, UserHandle user) {
mMainExecutor.execute(() -> {
SplitScreenController.this.startShortcut(packageName, shortcutId, stage, position,
options, user);
});
}
@Override
public void startIntent(PendingIntent intent, int stage, int position,
@Nullable Bundle options) {
mMainExecutor.execute(() -> {
SplitScreenController.this.startIntent(intent, stage, position, options);
});
}
}
}

View File

@@ -44,6 +44,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
@@ -65,7 +66,7 @@ import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.draganddrop.DragAndDropPolicy.Target;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreenController;
import org.junit.Before;
import org.junit.Test;
@@ -92,7 +93,7 @@ public class DragAndDropPolicyTest {
// Both the split-screen and start interface.
@Mock
private SplitScreen mSplitScreenStarter;
private SplitScreenController mSplitScreenStarter;
private DisplayLayout mLandscapeDisplayLayout;
private DisplayLayout mPortraitDisplayLayout;
@@ -127,8 +128,8 @@ public class DragAndDropPolicyTest {
mPortraitDisplayLayout = new DisplayLayout(info2, res, false, false);
mInsets = Insets.of(0, 0, 0, 0);
mPolicy = new DragAndDropPolicy(
mContext, mActivityTaskManager, mSplitScreenStarter, mSplitScreenStarter);
mPolicy = spy(new DragAndDropPolicy(
mContext, mActivityTaskManager, mSplitScreenStarter, mSplitScreenStarter));
mActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
mNonResizeableActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
setClipDataResizeable(mNonResizeableActivityClipData, false);
@@ -204,8 +205,8 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@Test
@@ -216,13 +217,13 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test
@@ -233,13 +234,13 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
reset(mSplitScreenStarter);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test
@@ -250,8 +251,8 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@Test
@@ -262,8 +263,8 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
}
@Test
@@ -275,14 +276,14 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
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(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test
@@ -294,14 +295,14 @@ public class DragAndDropPolicyTest {
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_UNDEFINED), eq(STAGE_POSITION_UNDEFINED), any());
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(mSplitScreenStarter).startClipDescription(any(), any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT));
verify(mSplitScreenStarter).startIntent(any(),
eq(STAGE_TYPE_SIDE), eq(STAGE_POSITION_BOTTOM_OR_RIGHT), any());
}
@Test

View File

@@ -180,7 +180,7 @@ public abstract class WMShellBaseModule {
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
@@ -205,7 +205,7 @@ public abstract class WMShellBaseModule {
static Optional<ShellCommandHandler> provideShellCommandHandler(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<SplitScreen> splitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
@@ -320,12 +320,21 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
static Optional<SplitScreen> provideSplitScreen(ShellTaskOrganizer shellTaskOrganizer,
static Optional<SplitScreen> provideSplitScreen(
Optional<SplitScreenController> splitScreenController) {
return splitScreenController.map((controller) -> controller.asSplitScreen());
}
@WMSingleton
@Provides
static Optional<SplitScreenController> provideSplitScreenController(
ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, Context context,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
@ShellMainThread ShellExecutor mainExecutor) {
if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
rootTaskDisplayAreaOrganizer));
rootTaskDisplayAreaOrganizer, mainExecutor));
} else {
return Optional.empty();
}