Merge changes Icb7ba7d1,If6d5e6ec into udc-dev

* changes:
  Fix black screen when recents finished after split
  Migrate moveToStage shell transition
This commit is contained in:
Tony Huang
2023-04-29 03:29:50 +00:00
committed by Android (Google) Code Review
5 changed files with 109 additions and 50 deletions

View File

@@ -59,4 +59,17 @@ public class SplitScreenConstants {
/** Flag applied to a transition change to identify it as a divider bar for animation. */
public static final int FLAG_IS_DIVIDER_BAR = FLAG_FIRST_CUSTOM;
public static final String splitPositionToString(@SplitPosition int pos) {
switch (pos) {
case SPLIT_POSITION_UNDEFINED:
return "SPLIT_POSITION_UNDEFINED";
case SPLIT_POSITION_TOP_OR_LEFT:
return "SPLIT_POSITION_TOP_OR_LEFT";
case SPLIT_POSITION_BOTTOM_OR_RIGHT:
return "SPLIT_POSITION_BOTTOM_OR_RIGHT";
default:
return "UNKNOWN";
}
}
}

View File

@@ -39,6 +39,7 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIV
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.common.split.SplitScreenConstants.splitPositionToString;
import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
@@ -378,40 +379,18 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitPosition int stagePosition,
WindowContainerTransaction wct) {
StageTaskListener targetStage;
int sideStagePosition;
if (isSplitScreenVisible()) {
// If the split screen is foreground, retrieves target stage based on position.
targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage;
sideStagePosition = mSideStagePosition;
prepareEnterSplitScreen(wct, task, stagePosition);
if (ENABLE_SHELL_TRANSITIONS) {
mSplitTransitions.startEnterTransition(TRANSIT_TO_FRONT, wct,
null, this, null /* consumedCallback */, null /* finishedCallback */,
isSplitScreenVisible()
? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN);
} else {
targetStage = mSideStage;
sideStagePosition = stagePosition;
}
if (!isSplitActive()) {
mSplitLayout.init();
prepareEnterSplitScreen(wct, task, stagePosition);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
setDividerVisibility(true, t);
});
} else {
setSideStagePosition(sideStagePosition, wct);
targetStage.addTask(task, wct);
targetStage.evictAllChildren(wct);
if (!isSplitScreenVisible()) {
final StageTaskListener anotherStage = targetStage == mMainStage
? mSideStage : mMainStage;
anotherStage.reparentTopTask(wct);
anotherStage.evictAllChildren(wct);
wct.reorder(mRootTaskInfo.token, true);
}
setRootForceTranslucent(false, wct);
mSyncQueue.queue(wct);
}
// Due to drag already pip task entering split by this method so need to reset flag here.
mIsDropEntering = false;
return true;
@@ -1509,9 +1488,51 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
*/
void prepareEnterSplitScreen(WindowContainerTransaction wct,
@Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) {
if (mMainStage.isActive()) return;
onSplitScreenEnter();
if (isSplitActive()) {
prepareBringSplit(wct, taskInfo, startPosition);
} else {
prepareActiveSplit(wct, taskInfo, startPosition);
}
}
private void prepareBringSplit(WindowContainerTransaction wct,
@Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) {
StageTaskListener targetStage;
if (isSplitScreenVisible()) {
// If the split screen is foreground, retrieves target stage based on position.
targetStage = startPosition == mSideStagePosition ? mSideStage : mMainStage;
} else {
targetStage = mSideStage;
}
if (taskInfo != null) {
wct.startTask(taskInfo.taskId,
resolveStartStage(STAGE_TYPE_UNDEFINED, startPosition, null, wct));
targetStage.evictAllChildren(wct);
}
// If running background, we need to reparent current top visible task to another stage
// and evict all tasks current under its.
if (!isSplitScreenVisible()) {
// Recreate so we need to reset position rather than keep position of background split.
mSplitLayout.resetDividerPosition();
updateWindowBounds(mSplitLayout, wct);
final StageTaskListener anotherStage = targetStage == mMainStage
? mSideStage : mMainStage;
anotherStage.evictAllChildren(wct);
anotherStage.reparentTopTask(wct);
wct.reorder(mRootTaskInfo.token, true);
setRootForceTranslucent(false, wct);
}
}
private void prepareActiveSplit(WindowContainerTransaction wct,
@Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) {
if (!ENABLE_SHELL_TRANSITIONS) {
// Legacy transition we need to create divider here, shell transition case we will
// create it on #finishEnterSplitScreen
mSplitLayout.init();
}
if (taskInfo != null) {
setSideStagePosition(startPosition, wct);
mSideStage.addTask(taskInfo, wct);
@@ -2383,7 +2404,17 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (taskInfo == null || !taskInfo.hasParentTask()) continue;
if (taskInfo == null) continue;
if (taskInfo.token.equals(mRootTaskInfo.token)) {
if (isOpeningType(change.getMode())) {
// Split is opened by someone so set it as visible.
setSplitsVisible(true);
} else if (isClosingType(change.getMode())) {
// Split is closed by someone so set it as invisible.
setSplitsVisible(false);
}
continue;
}
final StageTaskListener stage = getStageOfTask(taskInfo);
if (stage == null) continue;
if (isOpeningType(change.getMode())) {
@@ -2823,12 +2854,18 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final String childPrefix = innerPrefix + " ";
pw.println(prefix + TAG + " mDisplayId=" + mDisplayId);
pw.println(innerPrefix + "mDividerVisible=" + mDividerVisible);
pw.println(innerPrefix + "isSplitActive=" + isSplitActive());
pw.println(innerPrefix + "isSplitVisible=" + isSplitScreenVisible());
pw.println(innerPrefix + "MainStage");
pw.println(childPrefix + "stagePosition=" + getMainStagePosition());
pw.println(childPrefix + "stagePosition=" + splitPositionToString(getMainStagePosition()));
pw.println(childPrefix + "isActive=" + mMainStage.isActive());
mMainStage.dump(pw, childPrefix);
pw.println(innerPrefix + "MainStageListener");
mMainStageListener.dump(pw, childPrefix);
pw.println(innerPrefix + "SideStage");
pw.println(childPrefix + "stagePosition=" + getSideStagePosition());
pw.println(childPrefix + "stagePosition=" + splitPositionToString(getSideStagePosition()));
mSideStage.dump(pw, childPrefix);
pw.println(innerPrefix + "SideStageListener");
mSideStageListener.dump(pw, childPrefix);
if (mMainStage.isActive()) {
pw.println(innerPrefix + "SplitLayout");

View File

@@ -421,6 +421,13 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
final String childPrefix = innerPrefix + " ";
pw.println(prefix + this);
if (mChildrenTaskInfo.size() > 0) {
pw.println(prefix + "Children list:");
for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i);
pw.println(childPrefix + "Task#" + i + " taskID=" + taskInfo.taskId
+ " baseActivity=" + taskInfo.baseActivity);
}
}
}
}

View File

@@ -73,7 +73,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
/** Pip was entered while handling an intent with its own remoteTransition. */
static final int TYPE_OPTIONS_REMOTE_AND_PIP_CHANGE = 3;
/** Recents transition while split-screen active. */
/** Recents transition while split-screen foreground. */
static final int TYPE_RECENTS_DURING_SPLIT = 4;
/** The default animation for this mixed transition. */
@@ -152,7 +152,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@NonNull TransitionRequestInfo request) {
if (mPipHandler.requestHasPipEnter(request) && mSplitHandler.isSplitScreenVisible()) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a PiP-enter request while "
+ "Split-Screen is active, so treat it as Mixed.");
+ "Split-Screen is foreground, so treat it as Mixed.");
if (request.getRemoteTransition() != null) {
throw new IllegalStateException("Unexpected remote transition in"
+ "pip-enter-from-split request");
@@ -183,13 +183,13 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
mixed.mLeftoversHandler = handler.first;
mActiveTransitions.add(mixed);
return handler.second;
} else if (mSplitHandler.isSplitActive()
} else if (mSplitHandler.isSplitScreenVisible()
&& isOpeningType(request.getType())
&& request.getTriggerTask() != null
&& request.getTriggerTask().getWindowingMode() == WINDOWING_MODE_FULLSCREEN
&& request.getTriggerTask().getActivityType() == ACTIVITY_TYPE_HOME) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a going-home request while "
+ "Split-Screen is active, so treat it as Mixed.");
+ "Split-Screen is foreground, so treat it as Mixed.");
Pair<Transitions.TransitionHandler, WindowContainerTransaction> handler =
mPlayer.dispatchRequest(transition, request, this);
if (handler == null) {
@@ -211,7 +211,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@Override
public Transitions.TransitionHandler handleRecentsRequest(WindowContainerTransaction outWCT) {
if (mRecentsHandler != null && mSplitHandler.isSplitActive()) {
if (mRecentsHandler != null && mSplitHandler.isSplitScreenVisible()) {
return this;
}
return null;
@@ -219,9 +219,9 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@Override
public void setRecentsTransition(IBinder transition) {
if (mSplitHandler.isSplitActive()) {
if (mSplitHandler.isSplitScreenVisible()) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Got a recents request while "
+ "Split-Screen is active, so treat it as Mixed.");
+ "Split-Screen is foreground, so treat it as Mixed.");
final MixedTransition mixed = new MixedTransition(
MixedTransition.TYPE_RECENTS_DURING_SPLIT, transition);
mixed.mLeftoversHandler = mRecentsHandler;
@@ -351,7 +351,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animating a mixed transition for "
+ "entering PIP while Split-Screen is active.");
+ "entering PIP while Split-Screen is foreground.");
TransitionInfo.Change pipChange = null;
TransitionInfo.Change wallpaper = null;
final TransitionInfo everythingElse = subCopy(info, TRANSIT_TO_BACK, true /* changes */);

View File

@@ -152,10 +152,15 @@ public class StageCoordinatorTests extends ShellTestCase {
when(mStageCoordinator.isSplitActive()).thenReturn(true);
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
final WindowContainerTransaction wct = new WindowContainerTransaction();
final WindowContainerTransaction wct = spy(new WindowContainerTransaction());
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
verify(mSideStage).addTask(eq(task), eq(wct));
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
verify(mMainStage).reparentTopTask(eq(wct));
verify(mMainStage).evictAllChildren(eq(wct));
verify(mSideStage).evictAllChildren(eq(wct));
verify(mSplitLayout).resetDividerPosition();
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
}
@@ -171,14 +176,11 @@ public class StageCoordinatorTests extends ShellTestCase {
final WindowContainerTransaction wct = new WindowContainerTransaction();
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
verify(mMainStage).addTask(eq(task), eq(wct));
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
verify(mMainStage).evictAllChildren(eq(wct));
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition());
mStageCoordinator.moveToStage(task, SPLIT_POSITION_TOP_OR_LEFT, wct);
verify(mSideStage).addTask(eq(task), eq(wct));
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getSideStagePosition());
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
}
@Test