diff options
| author | 2021-01-21 21:33:05 +0000 | |
|---|---|---|
| committer | 2021-01-21 21:33:05 +0000 | |
| commit | 91464139ff9518217fecd4946753dfdcad3225b5 (patch) | |
| tree | fdf5525a712a64119032458ecabd8be84883bbaf | |
| parent | 7a52ee08146ba753bc6b532a73e00484b89bdfaf (diff) | |
| parent | a47141f5eef5e59dffdce257cee6341749b37c11 (diff) | |
Merge "drag-n-drop support for main/side stage split-screen"
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); |