Merge changes Id75611af,I1ead6501 into tm-qpr-dev

* changes:
  Support back to split
  Support back gesture to split pair in background
This commit is contained in:
Tony Huang
2022-12-13 16:44:35 +00:00
committed by Android (Google) Code Review
7 changed files with 151 additions and 63 deletions

View File

@@ -240,7 +240,7 @@ public class DragAndDropPolicy {
// Update launch options for the split side we are targeting. // Update launch options for the split side we are targeting.
position = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; position = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
// Add some data for logging splitscreen once it is invoked // Add some data for logging splitscreen once it is invoked
mSplitScreen.logOnDroppedToSplit(position, mLoggerSessionId); mSplitScreen.onDroppedToSplit(position, mLoggerSessionId);
} }
final ClipDescription description = data.getDescription(); final ClipDescription description = data.getDescription();

View File

@@ -16,9 +16,6 @@
package com.android.wm.shell.splitscreen; package com.android.wm.shell.splitscreen;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import android.content.Context; import android.content.Context;
import android.view.SurfaceSession; import android.view.SurfaceSession;
import android.window.WindowContainerToken; import android.window.WindowContainerToken;
@@ -34,8 +31,6 @@ import com.android.wm.shell.common.SyncTransactionQueue;
* @see StageCoordinator * @see StageCoordinator
*/ */
class MainStage extends StageTaskListener { class MainStage extends StageTaskListener {
private static final String TAG = MainStage.class.getSimpleName();
private boolean mIsActive = false; private boolean mIsActive = false;
MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId, MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
@@ -52,15 +47,8 @@ class MainStage extends StageTaskListener {
void activate(WindowContainerTransaction wct, boolean includingTopTask) { void activate(WindowContainerTransaction wct, boolean includingTopTask) {
if (mIsActive) return; if (mIsActive) return;
final WindowContainerToken rootToken = mRootTaskInfo.token;
if (includingTopTask) { if (includingTopTask) {
wct.reparentTasks( reparentTopTask(wct);
null /* currentParent */,
rootToken,
CONTROLLED_WINDOWING_MODES,
CONTROLLED_ACTIVITY_TYPES,
true /* onTop */,
true /* reparentTopOnly */);
} }
mIsActive = true; mIsActive = true;

View File

@@ -121,7 +121,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
public static final int EXIT_REASON_SCREEN_LOCKED = 7; public static final int EXIT_REASON_SCREEN_LOCKED = 7;
public static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8; public static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8;
public static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9; public static final int EXIT_REASON_CHILD_TASK_ENTER_PIP = 9;
public static final int EXIT_REASON_FULLSCREEN_SHORTCUT = 10; public static final int EXIT_REASON_RECREATE_SPLIT = 10;
public static final int EXIT_REASON_FULLSCREEN_SHORTCUT = 11;
@IntDef(value = { @IntDef(value = {
EXIT_REASON_UNKNOWN, EXIT_REASON_UNKNOWN,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW, EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW,
@@ -133,6 +134,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
EXIT_REASON_SCREEN_LOCKED, EXIT_REASON_SCREEN_LOCKED,
EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP,
EXIT_REASON_CHILD_TASK_ENTER_PIP, EXIT_REASON_CHILD_TASK_ENTER_PIP,
EXIT_REASON_RECREATE_SPLIT,
EXIT_REASON_FULLSCREEN_SHORTCUT, EXIT_REASON_FULLSCREEN_SHORTCUT,
}) })
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@@ -470,7 +472,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
*/ */
public void startShortcut(String packageName, String shortcutId, @SplitPosition int position, public void startShortcut(String packageName, String shortcutId, @SplitPosition int position,
@Nullable Bundle options, UserHandle user, @NonNull InstanceId instanceId) { @Nullable Bundle options, UserHandle user, @NonNull InstanceId instanceId) {
mStageCoordinator.getLogger().enterRequested(instanceId, ENTER_REASON_LAUNCHER); mStageCoordinator.onRequestToSplit(instanceId, ENTER_REASON_LAUNCHER);
startShortcut(packageName, shortcutId, position, options, user); startShortcut(packageName, shortcutId, position, options, user);
} }
@@ -518,7 +520,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
*/ */
public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent,
@SplitPosition int position, @Nullable Bundle options, @NonNull InstanceId instanceId) { @SplitPosition int position, @Nullable Bundle options, @NonNull InstanceId instanceId) {
mStageCoordinator.getLogger().enterRequested(instanceId, ENTER_REASON_LAUNCHER); mStageCoordinator.onRequestToSplit(instanceId, ENTER_REASON_LAUNCHER);
startIntent(intent, fillInIntent, position, options); startIntent(intent, fillInIntent, position, options);
} }
@@ -784,10 +786,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return splitTasksLayer; return splitTasksLayer;
} }
/** /**
* Sets drag info to be logged when splitscreen is entered. * Drop callback when splitscreen is entered.
*/ */
public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) { public void onDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) {
mStageCoordinator.logOnDroppedToSplit(position, dragSessionId); mStageCoordinator.onDroppedToSplit(position, dragSessionId);
} }
/** /**
@@ -815,6 +817,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return "APP_DOES_NOT_SUPPORT_MULTIWINDOW"; return "APP_DOES_NOT_SUPPORT_MULTIWINDOW";
case EXIT_REASON_CHILD_TASK_ENTER_PIP: case EXIT_REASON_CHILD_TASK_ENTER_PIP:
return "CHILD_TASK_ENTER_PIP"; return "CHILD_TASK_ENTER_PIP";
case EXIT_REASON_RECREATE_SPLIT:
return "RECREATE_SPLIT";
default: default:
return "unknown reason, reason int = " + exitReason; return "unknown reason, reason int = " + exitReason;
} }

View File

@@ -21,9 +21,11 @@ import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED_
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__UNKNOWN_ENTER; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__UNKNOWN_ENTER;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__CHILD_TASK_ENTER_PIP;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED;
@@ -37,9 +39,11 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASO
import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_UNKNOWN; import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_UNKNOWN;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED;
@@ -182,6 +186,10 @@ public class SplitscreenEventLogger {
return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED; return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED;
case EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP: case EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP:
return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP; return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
case EXIT_REASON_CHILD_TASK_ENTER_PIP:
return SPLITSCREEN_UICHANGED__EXIT_REASON__CHILD_TASK_ENTER_PIP;
case EXIT_REASON_RECREATE_SPLIT:
return SPLITSCREEN_UICHANGED__EXIT_REASON__RECREATE_SPLIT;
case EXIT_REASON_FULLSCREEN_SHORTCUT: case EXIT_REASON_FULLSCREEN_SHORTCUT:
return SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT; return SPLITSCREEN_UICHANGED__EXIT_REASON__FULLSCREEN_SHORTCUT;
case EXIT_REASON_UNKNOWN: case EXIT_REASON_UNKNOWN:

View File

@@ -49,10 +49,11 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASO
import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_MULTI_INSTANCE; import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_MULTI_INSTANCE;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_FULLSCREEN_SHORTCUT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RECREATE_SPLIT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP; import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP;
@@ -199,7 +200,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// and exit, since exit itself can trigger a number of changes that update the stages. // and exit, since exit itself can trigger a number of changes that update the stages.
private boolean mShouldUpdateRecents; private boolean mShouldUpdateRecents;
private boolean mExitSplitScreenOnHide; private boolean mExitSplitScreenOnHide;
private boolean mIsDividerRemoteAnimating; private boolean mIsSplitEntering;
private boolean mIsDropEntering;
private boolean mIsExiting; private boolean mIsExiting;
/** The target stage to dismiss to when unlock after folded. */ /** The target stage to dismiss to when unlock after folded. */
@@ -347,10 +349,19 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return mSplitTransitions; return mSplitTransitions;
} }
boolean isSplitScreenVisible() { public boolean isSplitScreenVisible() {
return mSideStageListener.mVisible && mMainStageListener.mVisible; return mSideStageListener.mVisible && mMainStageListener.mVisible;
} }
public boolean isSplitActive() {
return mMainStage.isActive();
}
boolean isSplitScreenRunningBackground() {
return !isSplitScreenVisible() && mMainStageListener.mHasChildren
&& mSideStageListener.mHasChildren;
}
@StageType @StageType
int getStageOfTask(int taskId) { int getStageOfTask(int taskId) {
if (mMainStage.containsTask(taskId)) { if (mMainStage.containsTask(taskId)) {
@@ -373,11 +384,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
targetStage = mSideStage; targetStage = mSideStage;
sideStagePosition = stagePosition; sideStagePosition = stagePosition;
} else { } else {
if (mMainStage.isActive()) { if (isSplitScreenVisible()) {
// If the split screen is activated, retrieves target stage based on position. // If the split screen is activated, retrieves target stage based on position.
targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage;
sideStagePosition = mSideStagePosition; sideStagePosition = mSideStagePosition;
} else { } else {
exitSplitIfBackground();
targetStage = mSideStage; targetStage = mSideStage;
sideStagePosition = stagePosition; sideStagePosition = stagePosition;
} }
@@ -673,6 +685,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent, @Nullable PendingIntent mainPendingIntent, @Nullable Intent mainFillInIntent,
@Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio, @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio,
RemoteAnimationAdapter adapter, InstanceId instanceId) { RemoteAnimationAdapter adapter, InstanceId instanceId) {
exitSplitIfBackground();
// Init divider first to make divider leash for remote animation target. // Init divider first to make divider leash for remote animation target.
mSplitLayout.init(); mSplitLayout.init();
mSplitLayout.setDivideRatio(splitRatio); mSplitLayout.setDivideRatio(splitRatio);
@@ -685,11 +698,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Set false to avoid record new bounds with old task still on top; // Set false to avoid record new bounds with old task still on top;
mShouldUpdateRecents = false; mShouldUpdateRecents = false;
mIsDividerRemoteAnimating = true; mIsSplitEntering = true;
final WindowContainerTransaction evictWct = new WindowContainerTransaction(); final WindowContainerTransaction evictWct = new WindowContainerTransaction();
prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct); if (isSplitScreenVisible()) {
prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct); mMainStage.evictAllChildren(evictWct);
mSideStage.evictAllChildren(evictWct);
}
IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() { IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
@Override @Override
@@ -769,7 +784,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void onRemoteAnimationFinishedOrCancelled(boolean cancel, private void onRemoteAnimationFinishedOrCancelled(boolean cancel,
WindowContainerTransaction evictWct) { WindowContainerTransaction evictWct) {
mIsDividerRemoteAnimating = false; mIsSplitEntering = false;
mShouldUpdateRecents = true; mShouldUpdateRecents = true;
// If any stage has no child after animation finished, it means that split will display // If any stage has no child after animation finished, it means that split will display
// nothing, such status will happen if task and intent is same app but not support // nothing, such status will happen if task and intent is same app but not support
@@ -781,6 +796,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitUnsupportedToast.show(); mSplitUnsupportedToast.show();
} else { } else {
mSyncQueue.queue(evictWct); mSyncQueue.queue(evictWct);
mSyncQueue.runInSync(t -> {
updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
});
} }
} }
@@ -815,7 +833,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
switch (stage) { switch (stage) {
case STAGE_TYPE_UNDEFINED: { case STAGE_TYPE_UNDEFINED: {
if (position != SPLIT_POSITION_UNDEFINED) { if (position != SPLIT_POSITION_UNDEFINED) {
if (mMainStage.isActive()) { if (isSplitScreenVisible()) {
// Use the stage of the specified position // Use the stage of the specified position
options = resolveStartStage( options = resolveStartStage(
position == mSideStagePosition ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN, position == mSideStagePosition ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN,
@@ -1045,7 +1063,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
}); });
mShouldUpdateRecents = false; mShouldUpdateRecents = false;
mIsDividerRemoteAnimating = false; mIsSplitEntering = false;
mSplitLayout.getInvisibleBounds(mTempRect1); mSplitLayout.getInvisibleBounds(mTempRect1);
if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) { if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
@@ -1064,6 +1082,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
wct.setSmallestScreenWidthDp(childrenToTop.mRootTaskInfo.token, wct.setSmallestScreenWidthDp(childrenToTop.mRootTaskInfo.token,
SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
} }
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
false /* reparentLeafTaskIfRelaunch */);
mSyncQueue.queue(wct); mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> { mSyncQueue.runInSync(t -> {
t.setWindowCrop(mMainStage.mRootLeash, null) t.setWindowCrop(mMainStage.mRootLeash, null)
@@ -1102,6 +1122,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
} }
/** Exit split screen if it still running background */
public void exitSplitIfBackground() {
if (!isSplitScreenRunningBackground()) return;
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
}
/** /**
* Overridden by child classes. * Overridden by child classes.
*/ */
@@ -1374,7 +1401,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
&& !ENABLE_SHELL_TRANSITIONS) { && !ENABLE_SHELL_TRANSITIONS) {
// Clear the divider remote animating flag as the divider will be re-rendered to apply // Clear the divider remote animating flag as the divider will be re-rendered to apply
// the new rotation config. // the new rotation config.
mIsDividerRemoteAnimating = false; mIsSplitEntering = false;
mSplitLayout.update(null /* t */); mSplitLayout.update(null /* t */);
onLayoutSizeChanged(mSplitLayout); onLayoutSizeChanged(mSplitLayout);
} }
@@ -1423,6 +1450,33 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}); });
} }
void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) {
if (stageListener == mSideStageListener && isSplitScreenRunningBackground()) {
// Handle entring split case here if split already running background.
if (mIsDropEntering) {
mSplitLayout.resetDividerPosition();
} else {
mSplitLayout.setDividerAtBorder(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
mMainStage.evictAllChildren(wct);
mSideStage.evictOtherChildren(wct, taskId);
mMainStage.reparentTopTask(wct);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
if (mIsDropEntering) {
updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
mIsDropEntering = false;
} else {
mSplitLayout.flingDividerToCenter();
}
});
}
}
private void onRootTaskVanished() { private void onRootTaskVanished() {
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
if (mRootTaskInfo != null) { if (mRootTaskInfo != null) {
@@ -1441,20 +1495,20 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return; return;
} }
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (!mainStageVisible) { if (!mainStageVisible) {
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
true /* setReparentLeafTaskIfRelaunch */);
// Both stages are not visible, check if it needs to dismiss split screen. // Both stages are not visible, check if it needs to dismiss split screen.
if (mExitSplitScreenOnHide if (mExitSplitScreenOnHide) {
// Don't dismiss split screen when both stages are not visible due to sleeping
// display.
|| (!mMainStage.mRootTaskInfo.isSleeping
&& !mSideStage.mRootTaskInfo.isSleeping)) {
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME); exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME);
} }
} else {
wct.setReparentLeafTaskIfRelaunch(mRootTaskInfo.token,
false /* setReparentLeafTaskIfRelaunch */);
} }
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> { mSyncQueue.runInSync(t -> {
t.setVisibility(mSideStage.mRootLeash, sideStageVisible)
.setVisibility(mMainStage.mRootLeash, mainStageVisible);
setDividerVisibility(mainStageVisible, t); setDividerVisibility(mainStageVisible, t);
}); });
} }
@@ -1479,7 +1533,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mDividerVisible = visible; mDividerVisible = visible;
sendSplitVisibilityChanged(); sendSplitVisibilityChanged();
if (mIsDividerRemoteAnimating) { if (mIsSplitEntering) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
" Skip animating divider bar due to it's remote animating."); " Skip animating divider bar due to it's remote animating.");
return; return;
@@ -1499,7 +1553,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
" Skip animating divider bar due to divider leash not ready."); " Skip animating divider bar due to divider leash not ready.");
return; return;
} }
if (mIsDividerRemoteAnimating) { if (mIsSplitEntering) {
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
" Skip animating divider bar due to it's remote animating."); " Skip animating divider bar due to it's remote animating.");
return; return;
@@ -1555,26 +1609,22 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (!hasChildren && !mIsExiting && mMainStage.isActive()) { if (!hasChildren && !mIsExiting && mMainStage.isActive()) {
if (isSideStage && mMainStageListener.mVisible) { if (isSideStage && mMainStageListener.mVisible) {
// Exit to main stage if side stage no longer has children. // Exit to main stage if side stage no longer has children.
if (ENABLE_SHELL_TRANSITIONS) {
exitSplitScreen(mMainStage, EXIT_REASON_APP_FINISHED);
} else {
mSplitLayout.flingDividerToDismiss( mSplitLayout.flingDividerToDismiss(
mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT, mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT,
EXIT_REASON_APP_FINISHED); EXIT_REASON_APP_FINISHED);
}
} else if (!isSideStage && mSideStageListener.mVisible) { } else if (!isSideStage && mSideStageListener.mVisible) {
// Exit to side stage if main stage no longer has children. // Exit to side stage if main stage no longer has children.
if (ENABLE_SHELL_TRANSITIONS) {
exitSplitScreen(mSideStage, EXIT_REASON_APP_FINISHED);
} else {
mSplitLayout.flingDividerToDismiss( mSplitLayout.flingDividerToDismiss(
mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT, mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT,
EXIT_REASON_APP_FINISHED); EXIT_REASON_APP_FINISHED);
} } else if (isSplitScreenRunningBackground()) {
// Do not exit to any stage due to running background.
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED);
} }
} else if (isSideStage && hasChildren && !mMainStage.isActive()) { } else if (isSideStage && hasChildren && !mMainStage.isActive()) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
mSplitLayout.init(); mSplitLayout.init();
final WindowContainerTransaction wct = new WindowContainerTransaction();
if (mLogger.isEnterRequestedByDrag()) { if (mLogger.isEnterRequestedByDrag()) {
prepareEnterSplitScreen(wct); prepareEnterSplitScreen(wct);
} else { } else {
@@ -1589,8 +1639,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSyncQueue.queue(wct); mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> { mSyncQueue.runInSync(t -> {
if (mLogger.isEnterRequestedByDrag()) { if (mIsDropEntering) {
updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
mIsDropEntering = false;
} else { } else {
mShowDecorImmediately = true; mShowDecorImmediately = true;
mSplitLayout.flingDividerToCenter(); mSplitLayout.flingDividerToCenter();
@@ -1945,10 +1996,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
} }
public boolean isSplitActive() {
return mMainStage.isActive();
}
@Override @Override
public void mergeAnimation(IBinder transition, TransitionInfo info, public void mergeAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t, IBinder mergeTarget, SurfaceControl.Transaction t, IBinder mergeTarget,
@@ -2304,10 +2351,28 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/** /**
* Sets drag info to be logged when splitscreen is next entered. * Sets drag info to be logged when splitscreen is next entered.
*/ */
public void logOnDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) { public void onDroppedToSplit(@SplitPosition int position, InstanceId dragSessionId) {
if (!isSplitScreenVisible()) {
mIsDropEntering = true;
}
if (isSplitScreenRunningBackground()) {
// Split running background, log exit first and start new enter request.
logExit(EXIT_REASON_RECREATE_SPLIT);
}
mLogger.enterRequestedByDrag(position, dragSessionId); mLogger.enterRequestedByDrag(position, dragSessionId);
} }
/**
* Sets info to be logged when splitscreen is next entered.
*/
public void onRequestToSplit(InstanceId sessionId, int enterReason) {
if (isSplitScreenRunningBackground()) {
// Split running background, log exit first and start new enter request.
logExit(EXIT_REASON_RECREATE_SPLIT);
}
mLogger.enterRequested(sessionId, enterReason);
}
/** /**
* Logs the exit of splitscreen. * Logs the exit of splitscreen.
*/ */
@@ -2342,6 +2407,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
StageCoordinator.this.onRootTaskAppeared(); StageCoordinator.this.onRootTaskAppeared();
} }
@Override
public void onChildTaskAppeared(int taskId) {
StageCoordinator.this.onChildTaskAppeared(this, taskId);
}
@Override @Override
public void onStatusChanged(boolean visible, boolean hasChildren) { public void onStatusChanged(boolean visible, boolean hasChildren) {
if (!mHasRootTask) return; if (!mHasRootTask) return;

View File

@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.RemoteAnimationTarget.MODE_OPENING; import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE; import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS; import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
@@ -69,6 +70,8 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
public interface StageListenerCallbacks { public interface StageListenerCallbacks {
void onRootTaskAppeared(); void onRootTaskAppeared();
void onChildTaskAppeared(int taskId);
void onStatusChanged(boolean visible, boolean hasChildren); void onStatusChanged(boolean visible, boolean hasChildren);
void onChildTaskStatusChanged(int taskId, boolean present, boolean visible); void onChildTaskStatusChanged(int taskId, boolean present, boolean visible);
@@ -185,6 +188,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
// Status is managed/synchronized by the transition lifecycle. // Status is managed/synchronized by the transition lifecycle.
return; return;
} }
mCallbacks.onChildTaskAppeared(taskId);
sendStatusChanged(); sendStatusChanged();
} else { } else {
throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
@@ -338,6 +342,14 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
} }
} }
void evictOtherChildren(WindowContainerTransaction wct, int taskId) {
for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) {
final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i);
if (taskId == taskInfo.taskId) continue;
wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
}
}
void evictNonOpeningChildren(RemoteAnimationTarget[] apps, WindowContainerTransaction wct) { void evictNonOpeningChildren(RemoteAnimationTarget[] apps, WindowContainerTransaction wct) {
final SparseArray<ActivityManager.RunningTaskInfo> toBeEvict = mChildrenTaskInfo.clone(); final SparseArray<ActivityManager.RunningTaskInfo> toBeEvict = mChildrenTaskInfo.clone();
for (int i = 0; i < apps.length; i++) { for (int i = 0; i < apps.length; i++) {
@@ -360,6 +372,12 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
} }
} }
void reparentTopTask(WindowContainerTransaction wct) {
wct.reparentTasks(null /* currentParent */, mRootTaskInfo.token,
CONTROLLED_WINDOWING_MODES, CONTROLLED_ACTIVITY_TYPES,
true /* onTop */, true /* reparentTopOnly */);
}
void resetBounds(WindowContainerTransaction wct) { void resetBounds(WindowContainerTransaction wct) {
wct.setBounds(mRootTaskInfo.token, null); wct.setBounds(mRootTaskInfo.token, null);
wct.setAppBounds(mRootTaskInfo.token, null); wct.setAppBounds(mRootTaskInfo.token, null);

View File

@@ -111,7 +111,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
@Override @Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition, public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) { @NonNull TransitionRequestInfo request) {
if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitActive()) { if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitScreenVisible()) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a PiP-enter request while " ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a PiP-enter request while "
+ "Split-Screen is active, so treat it as Mixed."); + "Split-Screen is active, so treat it as Mixed.");
if (request.getRemoteTransition() != null) { if (request.getRemoteTransition() != null) {