summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java61
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java74
8 files changed, 146 insertions, 25 deletions
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 9e88a260ac44..99a89a6b884f 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
@@ -300,7 +300,7 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
mTaskOrganizer, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mTransitions, mTransactionPool, mIconProvider,
mMainExecutor, mMainHandler, mRecentTasksOptional, mLaunchAdjacentController,
- mWindowDecorViewModel, mSplitState, mDesktopTasksController);
+ mWindowDecorViewModel, mSplitState, mDesktopTasksController, mRootTDAOrganizer);
}
@Override
@@ -441,7 +441,7 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
*/
public void prepareExitSplitScreen(WindowContainerTransaction wct,
@StageType int stageToTop, @ExitReason int reason) {
- mStageCoordinator.prepareExitSplitScreen(stageToTop, wct);
+ mStageCoordinator.prepareExitSplitScreen(stageToTop, wct, reason);
mStageCoordinator.clearSplitPairedInRecents(reason);
}
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 37c93518998a..511e426cc681 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
@@ -130,6 +130,7 @@ import com.android.internal.policy.FoldLockSettingsObserver;
import com.android.internal.protolog.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ComponentUtils;
import com.android.wm.shell.common.DisplayController;
@@ -168,6 +169,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -218,6 +220,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final SplitscreenEventLogger mLogger;
private final ShellExecutor mMainExecutor;
private final Handler mMainHandler;
+ private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
// Cache live tile tasks while entering recents, evict them from stages in finish transaction
// if user is opening another task(s).
private final ArrayList<Integer> mPausingTasks = new ArrayList<>();
@@ -354,7 +357,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
Handler mainHandler, Optional<RecentTasksController> recentTasks,
LaunchAdjacentController launchAdjacentController,
Optional<WindowDecorViewModel> windowDecorViewModel, SplitState splitState,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
@@ -367,6 +371,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mWindowDecorViewModel = windowDecorViewModel;
mSplitState = splitState;
mDesktopTasksController = desktopTasksController;
+ mRootTDAOrganizer = rootTDAOrganizer;
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_FULLSCREEN, this /* listener */);
@@ -425,7 +430,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
Handler mainHandler, Optional<RecentTasksController> recentTasks,
LaunchAdjacentController launchAdjacentController,
Optional<WindowDecorViewModel> windowDecorViewModel, SplitState splitState,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
@@ -447,6 +453,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mWindowDecorViewModel = windowDecorViewModel;
mSplitState = splitState;
mDesktopTasksController = desktopTasksController;
+ mRootTDAOrganizer = rootTDAOrganizer;
mDisplayController.addDisplayWindowListener(this);
transitions.addHandler(this);
@@ -880,7 +887,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void startSingleTask(int taskId, Bundle options, WindowContainerTransaction wct,
RemoteTransition remoteTransition) {
if (mMainStage.containsTask(taskId) || mSideStage.containsTask(taskId)) {
- prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
+ prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct, EXIT_REASON_FULLSCREEN_REQUEST);
}
if (mRecentTasks.isPresent()) {
mRecentTasks.get().removeSplitPair(taskId);
@@ -1433,7 +1440,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// on top and lead to no visible change.
clearSplitPairedInRecents(reason);
final WindowContainerTransaction wct = new WindowContainerTransaction();
- prepareExitSplitScreen(mLastActiveStage, wct);
+ prepareExitSplitScreen(mLastActiveStage, wct, reason);
mSplitTransitions.startDismissTransition(wct, this, mLastActiveStage, reason);
setSplitsVisible(false);
mBreakOnNextWake = false;
@@ -1527,7 +1534,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (!isSplitActive()) return;
final int stage = getStageOfTask(toTopTaskId);
final WindowContainerTransaction wct = new WindowContainerTransaction();
- prepareExitSplitScreen(stage, wct);
+ prepareExitSplitScreen(stage, wct, exitReason);
mSplitTransitions.startDismissTransition(wct, this, stage, exitReason);
// reset stages to their default sides.
setSideStagePosition(SPLIT_POSITION_BOTTOM_OR_RIGHT, null);
@@ -1646,7 +1653,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
* to be used when exiting split might be bundled with other window operations.
*/
void prepareExitSplitScreen(@StageType int stageToTop,
- @NonNull WindowContainerTransaction wct) {
+ @NonNull WindowContainerTransaction wct, @ExitReason int exitReason) {
if (!isSplitActive()) return;
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "prepareExitSplitScreen: stageToTop=%s",
stageTypeToString(stageToTop));
@@ -1657,6 +1664,26 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} else {
mSideStage.removeAllTasks(wct, stageToTop == STAGE_TYPE_SIDE);
}
+
+ if (exitReason != EXIT_REASON_DESKTOP_MODE) {
+ StageTaskListener toTopStage = stageToTop == STAGE_TYPE_MAIN ? mMainStage : mSideStage;
+ if (enableFlexibleSplit()) {
+ toTopStage = mStageOrderOperator.getAllStages().stream()
+ .filter(stage -> stage.getId() == stageToTop)
+ .findFirst().orElse(null);
+ }
+ final DisplayAreaInfo tdaInfo = mRootTDAOrganizer.getDisplayAreaInfo(mDisplayId);
+ Objects.requireNonNull(tdaInfo);
+ final int displayWindowingMode =
+ tdaInfo.configuration.windowConfiguration.getWindowingMode();
+ // In freeform-first env, we need to explicitly set the windowing mode when leaving
+ // the split-screen to be fullscreen.
+ final int targetWindowingMode = displayWindowingMode == WINDOWING_MODE_FREEFORM
+ ? WINDOWING_MODE_FULLSCREEN : WINDOWING_MODE_UNDEFINED;
+ toTopStage.doForAllChildTaskInfos(taskInfo -> {
+ wct.setWindowingMode(taskInfo.token, targetWindowingMode);
+ });
+ }
deactivateSplit(wct, stageToTop);
mSplitState.exit();
}
@@ -2331,7 +2358,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
stageType = isMainStage ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
- prepareExitSplitScreen(stageType, wct);
+ prepareExitSplitScreen(stageType, wct, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
clearSplitPairedInRecents(EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
mSplitTransitions.startDismissTransition(wct, StageCoordinator.this, stageType,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
@@ -2363,10 +2390,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
toTopStage.resetBounds(wct);
- prepareExitSplitScreen(dismissTop, wct);
+ prepareExitSplitScreen(dismissTop, wct, EXIT_REASON_DRAG_DIVIDER);
if (mRootTaskInfo != null) {
wct.setDoNotPip(mRootTaskInfo.token);
}
+
mSplitTransitions.startDismissTransition(wct, this, dismissTop, EXIT_REASON_DRAG_DIVIDER);
}
@@ -2801,7 +2829,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// The top should be the opposite side that is closing:
int dismissTop = getStageType(stage) == STAGE_TYPE_MAIN
? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN;
- prepareExitSplitScreen(dismissTop, out);
+ prepareExitSplitScreen(dismissTop, out, EXIT_REASON_APP_FINISHED);
mSplitTransitions.setDismissTransition(transition, dismissTop,
EXIT_REASON_APP_FINISHED);
} else if (isOpening && !mPausingTasks.isEmpty()) {
@@ -2809,7 +2837,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// recents, which means to dismiss the split pair to this task.
int dismissTop = getStageType(stage) == STAGE_TYPE_MAIN
? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
- prepareExitSplitScreen(dismissTop, out);
+ prepareExitSplitScreen(dismissTop, out, EXIT_REASON_APP_FINISHED);
mSplitTransitions.setDismissTransition(transition, dismissTop,
EXIT_REASON_APP_FINISHED);
} else if (!isSplitScreenVisible() && isOpening) {
@@ -2822,7 +2850,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// If the trigger task is in fullscreen and in split, exit split and place
// task on top
final int stageType = getStageOfTask(triggerTask.taskId);
- prepareExitSplitScreen(stageType, out);
+ prepareExitSplitScreen(stageType, out, EXIT_REASON_FULLSCREEN_REQUEST);
mSplitTransitions.setDismissTransition(transition, stageType,
EXIT_REASON_FULLSCREEN_REQUEST);
}
@@ -2850,7 +2878,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (anyStageContainsSingleFullscreenTask) {
// A splitting task is opening to fullscreen causes one side of the split empty,
// so appends operations to exit split.
- prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
+ prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out,
+ EXIT_REASON_FULLSCREEN_REQUEST);
}
} else if (type == TRANSIT_KEYGUARD_OCCLUDE && triggerTask.topActivity != null
&& isSplitScreenVisible()) {
@@ -2858,7 +2887,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// stage and move it to the top.
int top = triggerTask.topActivity.equals(mMainStage.mRootTaskInfo.topActivity)
? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
- prepareExitSplitScreen(top, out);
+ prepareExitSplitScreen(top, out, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
mSplitTransitions.setDismissTransition(transition, top,
EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
}
@@ -2940,7 +2969,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
topStage = STAGE_TYPE_SIDE;
}
}
- prepareExitSplitScreen(topStage, outWCT);
+ prepareExitSplitScreen(topStage, outWCT, EXIT_REASON_UNKNOWN);
}
}
@@ -3127,7 +3156,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// If there is a fullscreen opening change, we should not bring stage to top.
prepareExitSplitScreen(
!record.mContainShowFullscreenChange && isSplitScreenVisible()
- ? dismissTop : STAGE_TYPE_UNDEFINED, wct);
+ ? dismissTop : STAGE_TYPE_UNDEFINED, wct, EXIT_REASON_APP_FINISHED);
mSplitTransitions.startDismissTransition(wct, this, dismissTop,
EXIT_REASON_APP_FINISHED);
// This can happen in some pathological cases. For example:
@@ -3368,7 +3397,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
(sideChild != null ? STAGE_TYPE_SIDE : STAGE_TYPE_UNDEFINED);
pendingEnter.cancel(
(cancelWct, cancelT) -> {
- prepareExitSplitScreen(dismissTop, cancelWct);
+ prepareExitSplitScreen(dismissTop, cancelWct, EXIT_REASON_UNKNOWN);
logExit(EXIT_REASON_UNKNOWN);
});
Log.w(TAG, splitFailureMessage("startPendingEnterAnimation",
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 021f6595d984..194114db0169 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
@@ -379,6 +379,13 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
}
}
+ void doForAllChildTaskInfos(Consumer<ActivityManager.RunningTaskInfo> consumer) {
+ for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) {
+ final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i);
+ consumer.accept(taskInfo);
+ }
+ }
+
/** Collects all the current child tasks and prepares transaction to evict them to display. */
void evictAllChildren(WindowContainerTransaction wct) {
for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
index c5e158c6b452..d71b7a1183f4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
@@ -62,6 +62,7 @@ public class TvSplitScreenController extends SplitScreenController {
private final Optional<RecentTasksController> mRecentTasksOptional;
private final LaunchAdjacentController mLaunchAdjacentController;
private final SplitState mSplitState;
+ private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
private final Handler mMainHandler;
private final SystemWindows mSystemWindows;
@@ -109,6 +110,7 @@ public class TvSplitScreenController extends SplitScreenController {
mMainHandler = mainHandler;
mSystemWindows = systemWindows;
+ mRootTDAOrganizer = rootTDAOrganizer;
}
/**
@@ -121,7 +123,8 @@ public class TvSplitScreenController extends SplitScreenController {
mTaskOrganizer, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mTransitions, mTransactionPool,
mIconProvider, mMainExecutor, mMainHandler,
- mRecentTasksOptional, mLaunchAdjacentController, mSplitState, mSystemWindows);
+ mRecentTasksOptional, mLaunchAdjacentController, mSplitState, mSystemWindows,
+ mRootTDAOrganizer);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java
index e1bf12fc6082..d7f1ced1b432 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.os.Handler;
import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
@@ -55,11 +56,11 @@ public class TvStageCoordinator extends StageCoordinator
Optional<RecentTasksController> recentTasks,
LaunchAdjacentController launchAdjacentController,
SplitState splitState,
- SystemWindows systemWindows) {
+ SystemWindows systemWindows, RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
super(context, displayId, syncQueue, taskOrganizer, displayController, displayImeController,
displayInsetsController, transitions, transactionPool, iconProvider,
mainExecutor, mainHandler, recentTasks, launchAdjacentController,
- Optional.empty(), splitState, Optional.empty());
+ Optional.empty(), splitState, Optional.empty(), rootTDAOrganizer);
mTvSplitMenuController = new TvSplitMenuController(context, this,
systemWindows, mainHandler);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
index ae0c9d6cbf7c..414c0147660c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
@@ -26,6 +26,7 @@ import android.os.Handler;
import android.view.SurfaceControl;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.DisplayController;
@@ -83,12 +84,13 @@ public class SplitTestUtils {
Optional<RecentTasksController> recentTasks,
LaunchAdjacentController launchAdjacentController,
Optional<WindowDecorViewModel> windowDecorViewModel, SplitState splitState,
- Optional<DesktopTasksController> desktopTasksController) {
+ Optional<DesktopTasksController> desktopTasksController,
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
super(context, displayId, syncQueue, taskOrganizer, mainStage,
sideStage, displayController, imeController, insetsController, splitLayout,
transitions, transactionPool, mainExecutor, mainHandler, recentTasks,
launchAdjacentController, windowDecorViewModel, splitState,
- desktopTasksController);
+ desktopTasksController, rootTDAOrganizer);
// Prepare root task for testing.
mRootTask = new TestRunningTaskInfoBuilder().build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index b0fdfacd7d83..4211e4682810 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -47,6 +47,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -54,6 +55,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.SurfaceControl;
+import android.window.DisplayAreaInfo;
import android.window.IRemoteTransition;
import android.window.RemoteTransition;
import android.window.TransitionInfo;
@@ -65,6 +67,7 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.MockToken;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
@@ -121,6 +124,8 @@ public class SplitTransitionTests extends ShellTestCase {
private StageTaskListener mSideStage;
private StageCoordinator mStageCoordinator;
private SplitScreenTransitions mSplitScreenTransitions;
+ private final DisplayAreaInfo mDisplayAreaInfo = new DisplayAreaInfo(new MockToken().token(),
+ DEFAULT_DISPLAY, 0);
private ActivityManager.RunningTaskInfo mMainChild;
private ActivityManager.RunningTaskInfo mSideChild;
@@ -146,7 +151,9 @@ public class SplitTransitionTests extends ShellTestCase {
mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController,
mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions,
mTransactionPool, mMainExecutor, mMainHandler, Optional.empty(),
- mLaunchAdjacentController, Optional.empty(), mSplitState, Optional.empty());
+ mLaunchAdjacentController, Optional.empty(), mSplitState, Optional.empty(),
+ mRootTDAOrganizer);
+ when(mRootTDAOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(mDisplayAreaInfo);
mStageCoordinator.setMixedHandler(mMixedHandler);
mSplitScreenTransitions = mStageCoordinator.getSplitTransitions();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 7a88ace3f85f..5851cbf9b933 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -17,6 +17,8 @@
package com.android.wm.shell.splitscreen;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -27,11 +29,14 @@ import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSIT
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 static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
+import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DESKTOP_MODE;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -39,6 +44,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -56,6 +62,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.view.SurfaceControl;
+import android.window.DisplayAreaInfo;
import android.window.RemoteTransition;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -64,6 +71,8 @@ import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.wm.shell.MockToken;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
@@ -94,6 +103,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Optional;
+import java.util.function.Consumer;
/**
* Tests for {@link StageCoordinator}
@@ -125,6 +135,8 @@ public class StageCoordinatorTests extends ShellTestCase {
private DefaultMixedHandler mDefaultMixedHandler;
@Mock
private SplitState mSplitState;
+ @Mock
+ private RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
private final Rect mBounds1 = new Rect(10, 20, 30, 40);
private final Rect mBounds2 = new Rect(5, 10, 15, 20);
@@ -138,6 +150,10 @@ public class StageCoordinatorTests extends ShellTestCase {
private final TestShellExecutor mMainExecutor = new TestShellExecutor();
private final ShellExecutor mAnimExecutor = new TestShellExecutor();
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+ private final DisplayAreaInfo mDisplayAreaInfo = new DisplayAreaInfo(new MockToken().token(),
+ DEFAULT_DISPLAY, 0);
+ private final ActivityManager.RunningTaskInfo mMainChildTaskInfo =
+ new TestRunningTaskInfoBuilder().setVisible(true).build();
@Before
@UiThreadTest
@@ -148,9 +164,10 @@ public class StageCoordinatorTests extends ShellTestCase {
mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool,
mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController,
- Optional.empty(), mSplitState, Optional.empty()));
+ Optional.empty(), mSplitState, Optional.empty(), mRootTDAOrganizer));
mDividerLeash = new SurfaceControl.Builder().setName("fakeDivider").build();
+ when(mRootTDAOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)).thenReturn(mDisplayAreaInfo);
when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1);
when(mSplitLayout.getBottomRightBounds()).thenReturn(mBounds2);
@@ -167,6 +184,12 @@ public class StageCoordinatorTests extends ShellTestCase {
mMainStage.mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
doReturn(mock(SplitDecorManager.class)).when(mMainStage).getSplitDecorManager();
doReturn(mock(SplitDecorManager.class)).when(mSideStage).getSplitDecorManager();
+
+ doAnswer(invocation -> {
+ Consumer<ActivityManager.RunningTaskInfo> consumer = invocation.getArgument(0);
+ consumer.accept(mMainChildTaskInfo);
+ return null;
+ }).when(mMainStage).doForAllChildTaskInfos(any());
}
@Test
@@ -454,6 +477,55 @@ public class StageCoordinatorTests extends ShellTestCase {
int windowingMode = wctCaptor.getValue().getChanges().get(binder).getWindowingMode();
assertEquals(windowingMode, WINDOWING_MODE_UNDEFINED);
}
+ @Test
+ public void testDismiss_freeformDisplay() {
+ mDisplayAreaInfo.configuration.windowConfiguration.setWindowingMode(
+ WINDOWING_MODE_FREEFORM);
+ when(mStageCoordinator.isSplitActive()).thenReturn(true);
+
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.prepareExitSplitScreen(STAGE_TYPE_MAIN, wct, EXIT_REASON_DRAG_DIVIDER);
+
+ assertEquals(wct.getChanges().get(mMainChildTaskInfo.token.asBinder()).getWindowingMode(),
+ WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testDismiss_freeformDisplayToDesktop() {
+ mDisplayAreaInfo.configuration.windowConfiguration.setWindowingMode(
+ WINDOWING_MODE_FREEFORM);
+ when(mStageCoordinator.isSplitActive()).thenReturn(true);
+
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.prepareExitSplitScreen(STAGE_TYPE_MAIN, wct, EXIT_REASON_DESKTOP_MODE);
+
+ WindowContainerTransaction.Change c =
+ wct.getChanges().get(mMainChildTaskInfo.token.asBinder());
+ assertFalse(c != null && c.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
+ }
+
+ @Test
+ public void testDismiss_fullscreenDisplay() {
+ when(mStageCoordinator.isSplitActive()).thenReturn(true);
+
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.prepareExitSplitScreen(STAGE_TYPE_MAIN, wct, EXIT_REASON_DRAG_DIVIDER);
+
+ assertEquals(wct.getChanges().get(mMainChildTaskInfo.token.asBinder()).getWindowingMode(),
+ WINDOWING_MODE_UNDEFINED);
+ }
+
+ @Test
+ public void testDismiss_fullscreenDisplayToDesktop() {
+ when(mStageCoordinator.isSplitActive()).thenReturn(true);
+
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ mStageCoordinator.prepareExitSplitScreen(STAGE_TYPE_MAIN, wct, EXIT_REASON_DESKTOP_MODE);
+
+ WindowContainerTransaction.Change c =
+ wct.getChanges().get(mMainChildTaskInfo.token.asBinder());
+ assertFalse(c != null && c.getWindowingMode() == WINDOWING_MODE_FULLSCREEN);
+ }
private Transitions createTestTransitions() {
ShellInit shellInit = new ShellInit(mMainExecutor);