summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Wale Ogunwale <ogunwale@google.com> 2021-01-21 21:33:05 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-01-21 21:33:05 +0000
commit91464139ff9518217fecd4946753dfdcad3225b5 (patch)
treefdf5525a712a64119032458ecabd8be84883bbaf
parent7a52ee08146ba753bc6b532a73e00484b89bdfaf (diff)
parenta47141f5eef5e59dffdce257cee6341749b37c11 (diff)
Merge "drag-n-drop support for main/side stage split-screen"
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java208
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java57
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java24
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java110
13 files changed, 265 insertions, 221 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index b43203dbfd77..0958a070c82d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -100,7 +100,7 @@ public class ShellInitImpl {
mSplitScreenOptional.ifPresent(SplitScreen::onOrganizerRegistered);
// Bind the splitscreen impl to the drag drop controller
- mDragAndDropController.initialize(mLegacySplitScreenOptional);
+ mDragAndDropController.initialize(mSplitScreenOptional);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
mTransitions.register(mShellTaskOrganizer);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index e17a943b5cb0..c27c92961c2b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -135,7 +135,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener {
final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
final DividerSnapAlgorithm.SnapTarget snapTarget =
- mSplitLayout.findSnapTarget(position, velocity);
+ mSplitLayout.findSnapTarget(position, velocity, false /* hardDismiss */);
mSplitLayout.snapToTarget(position, snapTarget);
break;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index d77def54c87e..60231df37370 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -188,11 +188,11 @@ public class SplitLayout {
public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
switch (snapTarget.flag) {
case FLAG_DISMISS_START:
- mLayoutChangeListener.onSnappedToDismiss(false /* snappedToEnd */);
+ mLayoutChangeListener.onSnappedToDismiss(false /* bottomOrRight */);
mSplitWindowManager.setResizingSplits(false);
break;
case FLAG_DISMISS_END:
- mLayoutChangeListener.onSnappedToDismiss(true /* snappedToEnd */);
+ mLayoutChangeListener.onSnappedToDismiss(true /* bottomOrRight */);
mSplitWindowManager.setResizingSplits(false);
break;
default:
@@ -207,9 +207,11 @@ public class SplitLayout {
/**
* Returns {@link DividerSnapAlgorithm.SnapTarget} which matches passing position and velocity.
+ * If hardDismiss is set to {@code true}, it will be harder to reach dismiss target.
*/
- public DividerSnapAlgorithm.SnapTarget findSnapTarget(int position, float velocity) {
- return mDividerSnapAlgorithm.calculateSnapTarget(position, velocity);
+ public DividerSnapAlgorithm.SnapTarget findSnapTarget(int position, float velocity,
+ boolean hardDismiss) {
+ return mDividerSnapAlgorithm.calculateSnapTarget(position, velocity, hardDismiss);
}
private DividerSnapAlgorithm getSnapAlgorithm(Resources resources, Rect rootBounds) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index c8b4e10d4bb6..c8938ad40aba 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -52,7 +52,7 @@ import com.android.internal.protolog.common.ProtoLog;
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.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
@@ -66,7 +66,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
private final Context mContext;
private final DisplayController mDisplayController;
- private LegacySplitScreen mLegacySplitScreen;
+ private SplitScreen mSplitScreen;
private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>();
private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
@@ -76,8 +76,8 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
mDisplayController = displayController;
}
- public void initialize(Optional<LegacySplitScreen> splitscreen) {
- mLegacySplitScreen = splitscreen.orElse(null);
+ public void initialize(Optional<SplitScreen> splitscreen) {
+ mSplitScreen = splitscreen.orElse(null);
mDisplayController.addDisplayWindowListener(this);
}
@@ -104,7 +104,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
R.layout.global_drop_target, null);
rootView.setOnDragListener(this);
rootView.setVisibility(View.INVISIBLE);
- DragLayout dragLayout = new DragLayout(context, mLegacySplitScreen);
+ DragLayout dragLayout = new DragLayout(context, mSplitScreen);
rootView.addView(dragLayout,
new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
try {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index 4043d0bd3173..800150c0a93c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -34,6 +34,8 @@ 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 android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -59,13 +61,12 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
-import java.util.function.Consumer;
/**
* The policy for handling drag and drop operations to shell.
@@ -77,22 +78,22 @@ public class DragAndDropPolicy {
private final Context mContext;
private final ActivityTaskManager mActivityTaskManager;
private final Starter mStarter;
- private final LegacySplitScreen mLegacySplitScreen;
+ private final SplitScreen mSplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
private DragSession mSession;
- public DragAndDropPolicy(Context context, LegacySplitScreen legacySplitScreen) {
- this(context, ActivityTaskManager.getInstance(), legacySplitScreen,
- new DefaultStarter(context, legacySplitScreen));
+ public DragAndDropPolicy(Context context, SplitScreen splitScreen) {
+ this(context, ActivityTaskManager.getInstance(), splitScreen,
+ new DefaultStarter(context, splitScreen));
}
@VisibleForTesting
DragAndDropPolicy(Context context, ActivityTaskManager activityTaskManager,
- LegacySplitScreen legacySplitScreen, Starter starter) {
+ SplitScreen splitScreen, Starter starter) {
mContext = context;
mActivityTaskManager = activityTaskManager;
- mLegacySplitScreen = legacySplitScreen;
+ mSplitScreen = splitScreen;
mStarter = starter;
}
@@ -122,64 +123,54 @@ public class DragAndDropPolicy {
final int ih = h - insets.top - insets.bottom;
final int l = insets.left;
final int t = insets.top;
- final boolean isVerticalSplit = mSession.isPhone && !mSession.displayLayout.isLandscape();
- if (mSession.dragItemSupportsSplitscreen
- && mSession.runningTaskActType == ACTIVITY_TYPE_STANDARD
- && mSession.runningTaskWinMode == WINDOWING_MODE_FULLSCREEN
- && mSession.runningTaskIsResizeable) {
- // Allow splitting when there is a fullscreen standard activity running
- if (isVerticalSplit) {
- // TODO(b/169894807): For now, only allow splitting to the right/bottom until we
- // have split pairs
- mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(l, t, l + iw, t + ih / 2),
- new Rect(l, t, l + iw, t + ih),
- new Rect(0, 0, w, h)));
- mTargets.add(new Target(TYPE_SPLIT_BOTTOM,
- new Rect(l, t + ih / 2, l + iw, t + ih),
- new Rect(l, t + ih / 2, l + iw, t + ih),
- new Rect(0, h / 2, w, h)));
- } else {
- mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(l, t, l + iw / 2, t + ih),
- new Rect(l, t, l + iw, t + ih),
- new Rect(0, 0, w, h)));
- mTargets.add(new Target(TYPE_SPLIT_RIGHT,
- new Rect(l + iw / 2, t, l + iw, t + ih),
- new Rect(l + iw / 2, t, l + iw, t + ih),
- new Rect(w / 2, 0, w, h)));
- }
- } else if (mSession.dragItemSupportsSplitscreen
- && mLegacySplitScreen != null
- && mLegacySplitScreen.isDividerVisible()) {
+ final Rect displayRegion = new Rect(l, t, l + iw, t + ih);
+ final Rect fullscreenDrawRegion = new Rect(displayRegion);
+ final Rect fullscreenHitRegion = new Rect(displayRegion);
+ final boolean inLandscape = mSession.displayLayout.isLandscape();
+ final boolean inSplitScreen = mSplitScreen != null && mSplitScreen.isSplitScreenVisible();
+ // We allow splitting if we are already in split-screen or the running task is a standard
+ // task in fullscreen mode.
+ final boolean allowSplit = inSplitScreen
+ || (mSession.runningTaskActType == ACTIVITY_TYPE_STANDARD
+ && mSession.runningTaskWinMode == WINDOWING_MODE_FULLSCREEN);
+ if (allowSplit) {
// Already split, allow replacing existing split task
- // TODO(b/169894807): For now, only allow replacing the non-primary task until we have
- // split pairs
- final Rect secondarySplitRawBounds =
- mLegacySplitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds();
- final Rect secondarySplitBounds = new Rect(secondarySplitRawBounds);
- secondarySplitBounds.intersect(new Rect(l, t, l + iw, t + ih));
- if (isVerticalSplit) {
- mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(l, t, l + iw, secondarySplitRawBounds.top),
- new Rect(l, t, l + iw, t + ih),
- new Rect(0, 0, w, secondarySplitRawBounds.top)));
+ final Rect topOrLeftBounds = new Rect();
+ final Rect bottomOrRightBounds = new Rect();
+ mSplitScreen.getStageBounds(topOrLeftBounds, bottomOrRightBounds);
+ topOrLeftBounds.intersect(displayRegion);
+ bottomOrRightBounds.intersect(displayRegion);
+
+ if (inLandscape) {
+ final Rect leftHitRegion = new Rect();
+ final Rect leftDrawRegion = topOrLeftBounds;
+ final Rect rightHitRegion = new Rect();
+ final Rect rightDrawRegion = bottomOrRightBounds;
+
+ displayRegion.splitVertically(leftHitRegion, fullscreenHitRegion, rightHitRegion);
+
+ mTargets.add(
+ new Target(TYPE_FULLSCREEN, fullscreenHitRegion, fullscreenDrawRegion));
+ mTargets.add(new Target(TYPE_SPLIT_LEFT, leftHitRegion, leftDrawRegion));
+ mTargets.add(new Target(TYPE_SPLIT_RIGHT, rightHitRegion, rightDrawRegion));
+
} else {
- mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(l, t, secondarySplitRawBounds.left, t + ih),
- new Rect(l, t, l + iw, t + ih),
- new Rect(0, 0, w, h)));
+ final Rect topHitRegion = new Rect();
+ final Rect topDrawRegion = topOrLeftBounds;
+ final Rect bottomHitRegion = new Rect();
+ final Rect bottomDrawRegion = bottomOrRightBounds;
+
+ displayRegion.splitHorizontally(
+ topHitRegion, fullscreenHitRegion, bottomHitRegion);
+
+ mTargets.add(
+ new Target(TYPE_FULLSCREEN, fullscreenHitRegion, fullscreenDrawRegion));
+ mTargets.add(new Target(TYPE_SPLIT_TOP, topHitRegion, topDrawRegion));
+ mTargets.add(new Target(TYPE_SPLIT_BOTTOM, bottomHitRegion, bottomDrawRegion));
}
- mTargets.add(new Target(isVerticalSplit ? TYPE_SPLIT_BOTTOM : TYPE_SPLIT_RIGHT,
- new Rect(secondarySplitBounds),
- new Rect(secondarySplitBounds),
- new Rect(secondarySplitBounds)));
} else {
- // Otherwise only show the fullscreen target
- mTargets.add(new Target(TYPE_FULLSCREEN,
- new Rect(l, t, l + iw, t + ih),
- new Rect(l, t, l + iw, t + ih),
- new Rect(0, 0, w, h)));
+ // Split-screen not allowed, so only show the fullscreen target
+ mTargets.add(new Target(TYPE_FULLSCREEN, fullscreenHitRegion, fullscreenDrawRegion));
}
return mTargets;
}
@@ -208,58 +199,34 @@ public class DragAndDropPolicy {
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();
- boolean deferAppLaunchUntilSplit = false;
if (target.type == TYPE_FULLSCREEN) {
- if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) {
- // If in split, remove split and launch fullscreen
- mStarter.exitSplitScreen(mSession.runningTaskId);
- } else {
- // Not in split, fall through to launch
- }
- } else {
- if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) {
- // Split is already visible, just replace the task
- // TODO(b/169894807): Since we only allow replacing the non-primary target above
- // just fall through and start the activity
- } else {
- // Not in split, enter split now
- mStarter.enterSplitScreen(mSession.runningTaskId,
- target.type == TYPE_SPLIT_LEFT || target.type == TYPE_SPLIT_TOP);
- deferAppLaunchUntilSplit = true;
+ // Exit split stages if needed
+ mStarter.exitSplitScreen();
+ } else if (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;
+ if (!inSplitScreen) {
+ // Update the side stage position to match where we want to launch.
+ mSplitScreen.setSideStagePosition(position);
}
+ mSplitScreen.updateActivityOptions(opts, position);
}
- final Runnable startAppRunnable = () -> {
- Bundle opts = dragData.hasExtra(EXTRA_ACTIVITY_OPTIONS)
- ? dragData.getBundleExtra(EXTRA_ACTIVITY_OPTIONS)
- : null;
- 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);
- }
- };
- if (deferAppLaunchUntilSplit) {
- // TODO(b/169894807): The enterSplitScreen() call above will trigger the current task
- // into split, and we should wait for home and other tasks to be moved to
- // split-secondary before trying to launch the new secondary task. This can be removed
- // once we have app-pairs.
- mLegacySplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() {
- @Override
- public void accept(Boolean inSplit) {
- if (inSplit) {
- startAppRunnable.run();
- mLegacySplitScreen.unregisterInSplitScreenListener(this);
- }
- }
- });
+ 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 {
- startAppRunnable.run();
+ mStarter.startIntent(dragData.getParcelableExtra(EXTRA_PENDING_INTENT), opts);
}
}
@@ -323,7 +290,7 @@ public class DragAndDropPolicy {
UserHandle user);
void startIntent(PendingIntent intent, Bundle activityOptions);
void enterSplitScreen(int taskId, boolean leftOrTop);
- void exitSplitScreen(int taskId);
+ void exitSplitScreen();
}
/**
@@ -332,17 +299,17 @@ public class DragAndDropPolicy {
*/
private static class DefaultStarter implements Starter {
private final Context mContext;
- private final LegacySplitScreen mLegacySplitScreen;
+ private final SplitScreen mSplitScreen;
- public DefaultStarter(Context context, LegacySplitScreen legacySplitScreen) {
+ public DefaultStarter(Context context, SplitScreen splitScreen) {
mContext = context;
- mLegacySplitScreen = legacySplitScreen;
+ mSplitScreen = splitScreen;
}
@Override
public void startTask(int taskId, Bundle activityOptions) {
try {
- ActivityTaskManager.getService().startActivityFromRecents(taskId, null);
+ ActivityTaskManager.getService().startActivityFromRecents(taskId, activityOptions);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to launch task", e);
}
@@ -372,12 +339,14 @@ public class DragAndDropPolicy {
@Override
public void enterSplitScreen(int taskId, boolean leftOrTop) {
- mLegacySplitScreen.splitPrimaryTask();
+ mSplitScreen.moveToSideStage(taskId,
+ leftOrTop ? SIDE_STAGE_POSITION_TOP_OR_LEFT
+ : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT);
}
@Override
- public void exitSplitScreen(int taskId) {
- mLegacySplitScreen.dismissSplitToPrimaryTask();
+ public void exitSplitScreen() {
+ mSplitScreen.exitSplitScreen();
}
}
@@ -406,19 +375,16 @@ public class DragAndDropPolicy {
final Rect hitRegion;
// The approximate visual region for where the task will start
final Rect drawRegion;
- // The
- final Rect dropTargetBounds;
- public Target(@Type int t, Rect hit, Rect draw, Rect drop) {
+ public Target(@Type int t, Rect hit, Rect draw) {
type = t;
hitRegion = hit;
drawRegion = draw;
- dropTargetBounds = drop;
}
@Override
public String toString() {
- return "Target {hit=" + hitRegion + " drop=" + dropTargetBounds + "}";
+ return "Target {hit=" + hitRegion + " draw=" + drawRegion + "}";
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index a56fe8ded2e3..82c4e440fb15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -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.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.ArrayList;
@@ -61,7 +61,7 @@ public class DragLayout extends View {
private boolean mIsShowing;
private boolean mHasDropped;
- public DragLayout(Context context, LegacySplitScreen splitscreen) {
+ public DragLayout(Context context, SplitScreen splitscreen) {
super(context);
mPolicy = new DragAndDropPolicy(context, splitscreen);
mDisplayMargin = context.getResources().getDimensionPixelSize(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
index 552eba4ed5b3..7f98965d7f1f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -38,12 +38,6 @@ class MainStage extends StageTaskListener {
private boolean mIsActive = false;
- private static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
- private static final int[] CONTROLLED_WINDOWING_MODES =
- {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
- private static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
- {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};
-
MainStage(ShellTaskOrganizer taskOrganizer, int displayId,
StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue) {
super(taskOrganizer, displayId, callbacks, syncQueue);
@@ -92,7 +86,7 @@ class MainStage extends StageTaskListener {
null /* newParent */,
CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
CONTROLLED_ACTIVITY_TYPES,
- true /* onTop */)
+ false /* onTop */)
.reorder(rootToken, false /* onTop */);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index 5645c19d5c46..cd44e4b7cebf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.splitscreen;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
import android.app.ActivityManager;
import android.graphics.Rect;
import android.window.WindowContainerToken;
@@ -48,6 +50,17 @@ class SideStage extends StageTaskListener {
.reorder(rootToken, true);
}
+ boolean removeAllTasks(WindowContainerTransaction wct) {
+ if (mChildrenTaskInfo.size() == 0) return false;
+ wct.reparentTasks(
+ mRootTaskInfo.token,
+ null /* newParent */,
+ CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
+ CONTROLLED_ACTIVITY_TYPES,
+ false /* onTop */);
+ return true;
+ }
+
boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
if (task == null) return false;
@@ -57,4 +70,12 @@ class SideStage extends StageTaskListener {
.reparent(task.token, newParent, false /* onTop */);
return true;
}
+
+ int getTopVisibleTaskId() {
+ for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
+ final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.valueAt(i);
+ if (task.isVisible) return task.taskId;
+ }
+ return INVALID_TASK_ID;
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index 08c2856d6792..7c1b9d813851 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -18,6 +18,8 @@ package com.android.wm.shell.splitscreen;
import android.annotation.IntDef;
import android.app.ActivityManager;
+import android.graphics.Rect;
+import android.os.Bundle;
import androidx.annotation.NonNull;
@@ -61,6 +63,12 @@ public interface SplitScreen {
void setSideStagePosition(@SideStagePosition int sideStagePosition);
/** Hides the side-stage if it is currently visible. */
void setSideStageVisibility(boolean visible);
+ /** 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. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 55cfea5b6da3..27d3b81d41b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -20,6 +20,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
import android.app.ActivityManager;
import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
import androidx.annotation.NonNull;
@@ -69,7 +71,10 @@ public class SplitScreenController implements SplitScreen {
@Override
public boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition) {
final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
- return task != null && moveToSideStage(task, sideStagePosition);
+ if (task == null) {
+ throw new IllegalArgumentException("Unknown taskId" + taskId);
+ }
+ return moveToSideStage(task, sideStagePosition);
}
@Override
@@ -94,6 +99,21 @@ public class SplitScreenController implements SplitScreen {
}
@Override
+ public void exitSplitScreen() {
+ mStageCoordinator.exitSplitScreen();
+ }
+
+ @Override
+ public void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
+ mStageCoordinator.getStageBounds(outTopOrLeftBounds, outBottomOrRightBounds);
+ }
+
+ @Override
+ public void updateActivityOptions(Bundle opts, @SideStagePosition int position) {
+ mStageCoordinator.updateActivityOptions(opts, position);
+ }
+
+ @Override
public void dump(@NonNull PrintWriter pw, String prefix) {
pw.println(prefix + TAG);
if (mStageCoordinator != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 5c1d18e71800..dd41957935d7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -16,6 +16,8 @@
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;
@@ -25,6 +27,7 @@ import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_T
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Rect;
+import android.os.Bundle;
import android.view.SurfaceControl;
import android.window.DisplayAreaInfo;
import android.window.WindowContainerTransaction;
@@ -142,6 +145,31 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
mTaskOrganizer.applyTransaction(wct);
}
+ void exitSplitScreen() {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mSideStage.removeAllTasks(wct);
+ mMainStage.deactivate(wct);
+ mTaskOrganizer.applyTransaction(wct);
+ }
+
+ void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
+ outTopOrLeftBounds.set(mSplitLayout.getBounds1());
+ outBottomOrRightBounds.set(mSplitLayout.getBounds2());
+ }
+
+ void updateActivityOptions(Bundle opts, @SplitScreen.SideStagePosition int position) {
+ final StageTaskListener stage = position == mSideStagePosition ? mSideStage : mMainStage;
+ opts.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, stage.mRootTaskInfo.token);
+
+ if (!mMainStage.isActive()) {
+ // Activate the main stage in anticipation of an app launch.
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mMainStage.activate(getMainStageBounds(), wct);
+ mSideStage.setBounds(getSideStageBounds(), wct);
+ mTaskOrganizer.applyTransaction(wct);
+ }
+ }
+
private void onStageRootTaskAppeared(StageListenerImpl stageListener) {
if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -175,6 +203,12 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
}
}
+ if (!mainStageVisible && !sideStageVisible) {
+ // Exit split-screen if both stage are not visible.
+ // TODO: This is only a temporary request from UX and is likely to be removed soon...
+ exitSplitScreen();
+ }
+
if (mainStageVisible) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (sideStageVisible) {
@@ -252,10 +286,27 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
}
@Override
- public void onSnappedToDismiss(boolean snappedToEnd) {
- // TODO: What to do...what to do...
+ public void onSnappedToDismiss(boolean bottomOrRight) {
+ if (mSideStagePosition == SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT && bottomOrRight) {
+ // Main stage was fully expanded...Just side side-stage.
+ setSideStageVisibility(false);
+ } else {
+ // Side stage was fully expanded...Move its top task to the main stage
+ // and hide side-stage.
+ // TODO: Would UX prefer the side-stage go into fullscreen mode here?
+ final int taskId = mSideStage.getTopVisibleTaskId();
+ if (taskId == INVALID_TASK_ID) {
+ throw new IllegalStateException("Side stage doesn't have visible task? "
+ + mSideStage);
+ }
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mSideStage.removeTask(taskId, mMainStage.mRootTaskInfo.getToken(), wct);
+ mSideStage.setVisibility(false, wct);
+ mTaskOrganizer.applyTransaction(wct);
+ }
+
+ // Reset divider position.
mSplitLayout.resetDividerPosition();
- onBoundsChanged(mSplitLayout);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index efd42ce552b1..1aa7552c01eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -16,7 +16,10 @@
package com.android.wm.shell.splitscreen;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.CallSuper;
import android.app.ActivityManager;
@@ -45,6 +48,12 @@ import java.io.PrintWriter;
class StageTaskListener implements ShellTaskOrganizer.TaskListener {
private static final String TAG = StageTaskListener.class.getSimpleName();
+ protected static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
+ protected static final int[] CONTROLLED_WINDOWING_MODES =
+ {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
+ protected static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
+ {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};
+
/** Callback interface for listening to changes in a split-screen stage. */
public interface StageListenerCallbacks {
void onRootTaskAppeared();
@@ -69,7 +78,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
@Override
@CallSuper
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
- if (!taskInfo.hasParentTask()) {
+ if (mRootTaskInfo == null && !taskInfo.hasParentTask()) {
mRootLeash = leash;
mRootTaskInfo = taskInfo;
mCallbacks.onRootTaskAppeared();
@@ -78,7 +87,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
} else {
- throw new IllegalArgumentException("Unknown task: " + taskInfo);
+ throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
+ + "\n mRootTaskInfo: " + mRootTaskInfo);
}
sendStatusChanged();
}
@@ -93,7 +103,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
updateChildTaskSurface(
taskInfo, mChildrenLeashes.get(taskInfo.taskId), false /* firstAppeared */);
} else {
- throw new IllegalArgumentException("Unknown task: " + taskInfo);
+ throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
+ + "\n mRootTaskInfo: " + mRootTaskInfo);
}
sendStatusChanged();
}
@@ -110,7 +121,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
mChildrenLeashes.remove(taskId);
sendStatusChanged();
} else {
- throw new IllegalArgumentException("Unknown task: " + taskInfo);
+ throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
+ + "\n mRootTaskInfo: " + mRootTaskInfo);
}
}
@@ -143,6 +155,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
@Override
@CallSuper
public void dump(@NonNull PrintWriter pw, String prefix) {
-
+ final String innerPrefix = prefix + " ";
+ final String childPrefix = innerPrefix + " ";
+ pw.println(prefix + this);
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index 912418d0eebd..79bdaf43f171 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -26,7 +26,9 @@ import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM;
+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 junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
@@ -35,7 +37,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -52,7 +53,6 @@ import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Insets;
-import android.graphics.Rect;
import android.os.RemoteException;
import android.view.DisplayInfo;
@@ -61,20 +61,17 @@ 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.legacysplitscreen.DividerView;
-import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
-import java.util.function.Consumer;
/**
* Tests for the drag and drop policy.
@@ -90,12 +87,13 @@ public class DragAndDropPolicyTest {
private ActivityTaskManager mActivityTaskManager;
@Mock
- private LegacySplitScreen mLegacySplitScreen;
+ private SplitScreen mSplitScreen;
@Mock
private DragAndDropPolicy.Starter mStarter;
- private DisplayLayout mDisplayLayout;
+ private DisplayLayout mLandscapeDisplayLayout;
+ private DisplayLayout mPortraitDisplayLayout;
private Insets mInsets;
private DragAndDropPolicy mPolicy;
@@ -116,25 +114,19 @@ public class DragAndDropPolicyTest {
Resources res = mock(Resources.class);
Configuration config = new Configuration();
doReturn(config).when(res).getConfiguration();
+ doReturn(res).when(mContext).getResources();
DisplayInfo info = new DisplayInfo();
- info.logicalWidth = 100;
+ info.logicalWidth = 200;
info.logicalHeight = 100;
- mDisplayLayout = new DisplayLayout(info, res, false, false);
+ mLandscapeDisplayLayout = new DisplayLayout(info, res, false, false);
+ DisplayInfo info2 = new DisplayInfo();
+ info.logicalWidth = 100;
+ info.logicalHeight = 200;
+ mPortraitDisplayLayout = new DisplayLayout(info2, res, false, false);
mInsets = Insets.of(0, 0, 0, 0);
- DividerView divider = mock(DividerView.class);
- doReturn(divider).when(mLegacySplitScreen).getDividerView();
- doReturn(new Rect(50, 0, 100, 100)).when(divider)
- .getNonMinimizedSplitScreenSecondaryBounds();
-
- doAnswer((Answer<Void>) invocation -> {
- Consumer<Boolean> callback = invocation.getArgument(0);
- callback.accept(true);
- return null;
- }).when(mLegacySplitScreen).registerInSplitScreenListener(any());
-
mPolicy = new DragAndDropPolicy(
- mContext, mActivityTaskManager, mLegacySplitScreen, mStarter);
+ mContext, mActivityTaskManager, mSplitScreen, mStarter);
mActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
mNonResizeableActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
setClipDataResizeable(mNonResizeableActivityClipData, false);
@@ -149,7 +141,6 @@ public class DragAndDropPolicyTest {
mSplitPrimaryAppTask = createTaskInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
ACTIVITY_TYPE_STANDARD);
- setIsPhone(false);
setInSplitScreen(false);
setRunningTask(mFullscreenAppTask);
}
@@ -199,22 +190,14 @@ public class DragAndDropPolicyTest {
: ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
}
- private void setIsPhone(boolean isPhone) {
- Resources res = mock(Resources.class);
- Configuration config = mock(Configuration.class);
- config.smallestScreenWidthDp = isPhone ? 400 : 800;
- doReturn(config).when(res).getConfiguration();
- doReturn(res).when(mContext).getResources();
- }
-
private void setInSplitScreen(boolean inSplitscreen) {
- doReturn(inSplitscreen).when(mLegacySplitScreen).isDividerVisible();
+ doReturn(inSplitscreen).when(mSplitScreen).isSplitScreenVisible();
}
@Test
- public void testDragAppOverFullscreenHome_expectOnlyFullscreenTarget() throws RemoteException {
+ public void testDragAppOverFullscreenHome_expectOnlyFullscreenTarget() {
setRunningTask(mHomeTask);
- mPolicy.start(mDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
@@ -223,77 +206,66 @@ public class DragAndDropPolicyTest {
}
@Test
- public void testDragAppOverFullscreenApp_expectSplitScreenAndFullscreenTargets()
- throws RemoteException {
+ public void testDragAppOverFullscreenApp_expectSplitScreenAndFullscreenTargets() {
setRunningTask(mFullscreenAppTask);
- mPolicy.start(mDisplayLayout, mActivityClipData);
- // TODO(b/169894807): For now, only allow splitting to the right/bottom until we have split
- // pairs
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
ArrayList<Target> targets = assertExactTargetTypes(
- mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_RIGHT);
+ 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);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData);
- verify(mStarter).enterSplitScreen(anyInt(), eq(false));
verify(mStarter).startIntent(any(), any());
}
@Test
- public void testDragAppOverFullscreenAppPhone_expectVerticalSplitScreenAndFullscreenTargets()
- throws RemoteException {
- setIsPhone(true);
+ public void testDragAppOverFullscreenAppPhone_expectVerticalSplitScreenAndFullscreenTargets() {
setRunningTask(mFullscreenAppTask);
- mPolicy.start(mDisplayLayout, mActivityClipData);
- // TODO(b/169894807): For now, only allow splitting to the right/bottom until we have split
- // pairs
+ mPolicy.start(mPortraitDisplayLayout, mActivityClipData);
ArrayList<Target> targets = assertExactTargetTypes(
- mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_BOTTOM);
+ 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);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData);
- verify(mStarter).enterSplitScreen(anyInt(), eq(false));
verify(mStarter).startIntent(any(), any());
}
@Test
- public void testDragAppOverFullscreenNonResizeableApp_expectOnlyFullscreenTargets()
- throws RemoteException {
+ public void testDragAppOverFullscreenNonResizeableApp_expectOnlyFullscreenTargets() {
setRunningTask(mNonResizeableFullscreenAppTask);
- mPolicy.start(mDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
ArrayList<Target> targets = assertExactTargetTypes(
- mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
+ mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mStarter).startIntent(any(), any());
}
@Test
- public void testDragNonResizeableAppOverFullscreenApp_expectOnlyFullscreenTargets()
- throws RemoteException {
+ public void testDragNonResizeableAppOverFullscreenApp_expectOnlyFullscreenTargets() {
setRunningTask(mFullscreenAppTask);
- mPolicy.start(mDisplayLayout, mNonResizeableActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mNonResizeableActivityClipData);
ArrayList<Target> targets = assertExactTargetTypes(
- mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
+ mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mStarter).startIntent(any(), any());
}
@Test
- public void testDragAppOverSplitApp_expectFullscreenAndSplitTargets() throws RemoteException {
+ public void testDragAppOverSplitApp_expectFullscreenAndSplitTargets() {
setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask);
- mPolicy.start(mDisplayLayout, mActivityClipData);
- // TODO(b/169894807): For now, only allow splitting to the right/bottom until we have split
- // pairs
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
ArrayList<Target> targets = assertExactTargetTypes(
- mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_RIGHT);
+ mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mStarter).startIntent(any(), any());
@@ -305,16 +277,12 @@ public class DragAndDropPolicyTest {
}
@Test
- public void testDragAppOverSplitAppPhone_expectFullscreenAndVerticalSplitTargets()
- throws RemoteException {
- setIsPhone(true);
+ public void testDragAppOverSplitAppPhone_expectFullscreenAndVerticalSplitTargets() {
setInSplitScreen(true);
setRunningTask(mSplitPrimaryAppTask);
- mPolicy.start(mDisplayLayout, mActivityClipData);
- // TODO(b/169894807): For now, only allow splitting to the right/bottom until we have split
- // pairs
+ mPolicy.start(mPortraitDisplayLayout, mActivityClipData);
ArrayList<Target> targets = assertExactTargetTypes(
- mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_BOTTOM);
+ mPolicy.getTargets(mInsets), TYPE_FULLSCREEN, TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData);
verify(mStarter).startIntent(any(), any());
@@ -326,9 +294,9 @@ public class DragAndDropPolicyTest {
}
@Test
- public void testTargetHitRects() throws RemoteException {
+ public void testTargetHitRects() {
setRunningTask(mFullscreenAppTask);
- mPolicy.start(mDisplayLayout, mActivityClipData);
+ mPolicy.start(mLandscapeDisplayLayout, mActivityClipData);
ArrayList<Target> targets = mPolicy.getTargets(mInsets);
for (Target t : targets) {
assertTrue(mPolicy.getTargetAtLocation(t.hitRegion.left, t.hitRegion.top) == t);