Merge "Improve pip to split transition" into tm-qpr-dev
This commit is contained in:
@@ -1481,9 +1481,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
|||||||
applyFinishBoundsResize(wct, direction, false);
|
applyFinishBoundsResize(wct, direction, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final boolean isPipTopLeft =
|
applyFinishBoundsResize(wct, direction, isPipToTopLeft());
|
||||||
direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN && isPipToTopLeft();
|
// Use sync transaction to apply finish transaction for enter split case.
|
||||||
applyFinishBoundsResize(wct, direction, isPipTopLeft);
|
if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
|
||||||
|
mSyncTransactionQueue.runInSync(t -> {
|
||||||
|
t.merge(tx);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finishResizeForMenu(destinationBounds);
|
finishResizeForMenu(destinationBounds);
|
||||||
@@ -1520,7 +1524,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
|||||||
mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
|
mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
|
||||||
|
|
||||||
wct.setBounds(mToken, taskBounds);
|
wct.setBounds(mToken, taskBounds);
|
||||||
wct.setBoundsChangeTransaction(mToken, tx);
|
// Pip to split should use sync transaction to sync split bounds change.
|
||||||
|
if (direction != TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
|
||||||
|
wct.setBoundsChangeTransaction(mToken, tx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT
|
|||||||
import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit;
|
import static com.android.wm.shell.common.split.SplitScreenUtils.isValidToSplit;
|
||||||
import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
|
import static com.android.wm.shell.common.split.SplitScreenUtils.reverseSplitPosition;
|
||||||
import static com.android.wm.shell.common.split.SplitScreenUtils.samePackage;
|
import static com.android.wm.shell.common.split.SplitScreenUtils.samePackage;
|
||||||
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.SplitScreen.STAGE_TYPE_UNDEFINED;
|
||||||
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
|
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SPLIT_SCREEN;
|
||||||
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
|
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
|
||||||
@@ -89,7 +88,6 @@ import com.android.wm.shell.draganddrop.DragAndDropController;
|
|||||||
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
|
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
|
||||||
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
||||||
import com.android.wm.shell.recents.RecentTasksController;
|
import com.android.wm.shell.recents.RecentTasksController;
|
||||||
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
|
|
||||||
import com.android.wm.shell.sysui.KeyguardChangeListener;
|
import com.android.wm.shell.sysui.KeyguardChangeListener;
|
||||||
import com.android.wm.shell.sysui.ShellCommandHandler;
|
import com.android.wm.shell.sysui.ShellCommandHandler;
|
||||||
import com.android.wm.shell.sysui.ShellController;
|
import com.android.wm.shell.sysui.ShellController;
|
||||||
@@ -339,8 +337,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) {
|
public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) {
|
||||||
return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition,
|
return moveToStage(taskId, sideStagePosition, new WindowContainerTransaction());
|
||||||
new WindowContainerTransaction());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -351,13 +348,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
|||||||
mStageCoordinator.updateSurfaces(transaction);
|
mStageCoordinator.updateSurfaces(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean moveToStage(int taskId, @StageType int stageType,
|
private boolean moveToStage(int taskId, @SplitPosition int stagePosition,
|
||||||
@SplitPosition int stagePosition, WindowContainerTransaction wct) {
|
WindowContainerTransaction wct) {
|
||||||
final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
|
final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
throw new IllegalArgumentException("Unknown taskId" + taskId);
|
throw new IllegalArgumentException("Unknown taskId" + taskId);
|
||||||
}
|
}
|
||||||
return mStageCoordinator.moveToStage(task, stageType, stagePosition, wct);
|
return mStageCoordinator.moveToStage(task, stagePosition, wct);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeFromSideStage(int taskId) {
|
public boolean removeFromSideStage(int taskId) {
|
||||||
@@ -382,10 +379,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) {
|
public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) {
|
||||||
final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE;
|
|
||||||
final int stagePosition =
|
final int stagePosition =
|
||||||
leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
|
leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
|
||||||
moveToStage(taskId, stageType, stagePosition, wct);
|
moveToStage(taskId, stagePosition, wct);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
|
public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
|
||||||
|
|||||||
@@ -399,56 +399,43 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
|||||||
return STAGE_TYPE_UNDEFINED;
|
return STAGE_TYPE_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean moveToStage(ActivityManager.RunningTaskInfo task, @StageType int stageType,
|
boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitPosition int stagePosition,
|
||||||
@SplitPosition int stagePosition, WindowContainerTransaction wct) {
|
WindowContainerTransaction wct) {
|
||||||
StageTaskListener targetStage;
|
StageTaskListener targetStage;
|
||||||
int sideStagePosition;
|
int sideStagePosition;
|
||||||
if (stageType == STAGE_TYPE_MAIN) {
|
if (isSplitScreenVisible()) {
|
||||||
targetStage = mMainStage;
|
// If the split screen is foreground, retrieves target stage based on position.
|
||||||
sideStagePosition = reverseSplitPosition(stagePosition);
|
targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage;
|
||||||
} else if (stageType == STAGE_TYPE_SIDE) {
|
sideStagePosition = mSideStagePosition;
|
||||||
|
} else {
|
||||||
targetStage = mSideStage;
|
targetStage = mSideStage;
|
||||||
sideStagePosition = stagePosition;
|
sideStagePosition = stagePosition;
|
||||||
} else {
|
|
||||||
if (isSplitScreenVisible()) {
|
|
||||||
// If the split screen is activated, retrieves target stage based on position.
|
|
||||||
targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage;
|
|
||||||
sideStagePosition = mSideStagePosition;
|
|
||||||
} else {
|
|
||||||
// Exit split if it running background.
|
|
||||||
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RECREATE_SPLIT);
|
|
||||||
|
|
||||||
targetStage = mSideStage;
|
|
||||||
sideStagePosition = stagePosition;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isSplitActive()) {
|
if (!isSplitActive()) {
|
||||||
// prevent the fling divider to center transitioni if split screen didn't active.
|
mSplitLayout.init();
|
||||||
mIsDropEntering = true;
|
prepareEnterSplitScreen(wct, task, stagePosition);
|
||||||
|
mSyncQueue.queue(wct);
|
||||||
|
mSyncQueue.runInSync(t -> {
|
||||||
|
updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
|
||||||
|
});
|
||||||
|
} 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSideStagePosition(sideStagePosition, wct);
|
// Due to drag already pip task entering split by this method so need to reset flag here.
|
||||||
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
|
mIsDropEntering = false;
|
||||||
targetStage.evictAllChildren(evictWct);
|
|
||||||
|
|
||||||
// Apply surface bounds before animation start.
|
|
||||||
SurfaceControl.Transaction startT = mTransactionPool.acquire();
|
|
||||||
if (startT != null) {
|
|
||||||
updateSurfaceBounds(mSplitLayout, startT, false /* applyResizingOffset */);
|
|
||||||
startT.apply();
|
|
||||||
mTransactionPool.release(startT);
|
|
||||||
}
|
|
||||||
// reparent the task to an invisible split root will make the activity invisible. Reorder
|
|
||||||
// the root task to front to make the entering transition from pip to split smooth.
|
|
||||||
wct.reorder(mRootTaskInfo.token, true);
|
|
||||||
wct.reorder(targetStage.mRootTaskInfo.token, true);
|
|
||||||
targetStage.addTask(task, wct);
|
|
||||||
|
|
||||||
if (!evictWct.isEmpty()) {
|
|
||||||
wct.merge(evictWct, true /* transfer */);
|
|
||||||
}
|
|
||||||
mTaskOrganizer.applyTransaction(wct);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -144,39 +144,48 @@ public class StageCoordinatorTests extends ShellTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMoveToStage() {
|
public void testMoveToStage_splitActiveBackground() {
|
||||||
|
when(mStageCoordinator.isSplitActive()).thenReturn(true);
|
||||||
|
|
||||||
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
|
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
|
||||||
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
|
||||||
mStageCoordinator.moveToStage(task, STAGE_TYPE_MAIN, SPLIT_POSITION_BOTTOM_OR_RIGHT,
|
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
|
||||||
new WindowContainerTransaction());
|
verify(mSideStage).addTask(eq(task), eq(wct));
|
||||||
verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class));
|
|
||||||
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
|
|
||||||
|
|
||||||
mStageCoordinator.moveToStage(task, STAGE_TYPE_SIDE, SPLIT_POSITION_BOTTOM_OR_RIGHT,
|
|
||||||
new WindowContainerTransaction());
|
|
||||||
verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class));
|
|
||||||
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
|
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
|
||||||
|
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMoveToUndefinedStage() {
|
public void testMoveToStage_splitActiveForeground() {
|
||||||
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
|
when(mStageCoordinator.isSplitActive()).thenReturn(true);
|
||||||
|
|
||||||
// Verify move to undefined stage while split screen not activated moves task to side stage.
|
|
||||||
when(mStageCoordinator.isSplitScreenVisible()).thenReturn(false);
|
|
||||||
mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
|
|
||||||
mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_BOTTOM_OR_RIGHT,
|
|
||||||
new WindowContainerTransaction());
|
|
||||||
verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class));
|
|
||||||
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
|
|
||||||
|
|
||||||
// Verify move to undefined stage after split screen activated moves task based on position.
|
|
||||||
when(mStageCoordinator.isSplitScreenVisible()).thenReturn(true);
|
when(mStageCoordinator.isSplitScreenVisible()).thenReturn(true);
|
||||||
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
|
// Assume current side stage is top or left.
|
||||||
mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_TOP_OR_LEFT,
|
mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
|
||||||
new WindowContainerTransaction());
|
|
||||||
verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class));
|
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
|
||||||
assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
|
||||||
|
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
|
||||||
|
verify(mMainStage).addTask(eq(task), 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
|
||||||
|
public void testMoveToStage_splitInctive() {
|
||||||
|
final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
|
||||||
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
|
||||||
|
mStageCoordinator.moveToStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
|
||||||
|
verify(mStageCoordinator).prepareEnterSplitScreen(eq(wct), eq(task),
|
||||||
|
eq(SPLIT_POSITION_BOTTOM_OR_RIGHT));
|
||||||
|
assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user