Merge "Integrate pip to split flow with shell-transition"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f3de83a73b
@@ -309,10 +309,11 @@ public class WMShellModule {
|
||||
PipAnimationController pipAnimationController, PipBoundsAlgorithm pipBoundsAlgorithm,
|
||||
PipBoundsState pipBoundsState, PipTransitionState pipTransitionState,
|
||||
PhonePipMenuController pipMenuController,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper) {
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
Optional<SplitScreenController> splitScreenOptional) {
|
||||
return new PipTransition(context, pipBoundsState, pipTransitionState, pipMenuController,
|
||||
pipBoundsAlgorithm, pipAnimationController, transitions, shellTaskOrganizer,
|
||||
pipSurfaceTransactionHelper);
|
||||
pipSurfaceTransactionHelper, splitScreenOptional);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
|
||||
@@ -25,6 +25,8 @@ import static android.util.RotationUtils.rotateBounds;
|
||||
|
||||
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
|
||||
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
|
||||
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.pip.PipAnimationController.ANIM_TYPE_ALPHA;
|
||||
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
|
||||
import static com.android.wm.shell.pip.PipAnimationController.FRACTION_START;
|
||||
@@ -40,6 +42,10 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI
|
||||
import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;
|
||||
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
|
||||
import static com.android.wm.shell.pip.PipAnimationController.isRemovePipDirection;
|
||||
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -394,6 +400,18 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mPipUiEventLoggerLogger.log(
|
||||
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_EXPAND_TO_FULLSCREEN);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
|
||||
if (ENABLE_SHELL_TRANSITIONS) {
|
||||
if (requestEnterSplit && mSplitScreenOptional.isPresent()) {
|
||||
mSplitScreenOptional.get().prepareEnterSplitScreen(wct, mTaskInfo,
|
||||
isPipTopLeft()
|
||||
? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
|
||||
mPipTransitionController.startExitTransition(
|
||||
TRANSIT_EXIT_PIP_TO_SPLIT, wct, null /* destinationBounds */);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final Rect destinationBounds = mPipBoundsState.getDisplayBounds();
|
||||
final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit)
|
||||
? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
|
||||
@@ -414,7 +432,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
|
||||
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
mPipTransitionController.startTransition(destinationBounds, wct);
|
||||
mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct, destinationBounds);
|
||||
return;
|
||||
}
|
||||
mSyncTransactionQueue.queue(wct);
|
||||
@@ -479,7 +497,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
wct.setBounds(mToken, null);
|
||||
wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
|
||||
wct.reorder(mToken, false);
|
||||
mPipTransitionController.startTransition(null, wct);
|
||||
mPipTransitionController.startExitTransition(TRANSIT_REMOVE_PIP, wct,
|
||||
null /* destinationBounds */);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1280,7 +1299,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct,
|
||||
@PipAnimationController.TransitionDirection int direction, boolean wasPipTopLeft) {
|
||||
if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
|
||||
mSplitScreenOptional.get().enterSplitScreen(mTaskInfo.taskId, wasPipTopLeft, wct);
|
||||
mSplitScreenOptional.ifPresent(splitScreenController ->
|
||||
splitScreenController.enterSplitScreen(mTaskInfo.taskId, wasPipTopLeft, wct));
|
||||
} else {
|
||||
mTaskOrganizer.applyTransaction(wct);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,9 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI
|
||||
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
|
||||
import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;
|
||||
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
|
||||
import static com.android.wm.shell.transition.Transitions.isOpeningType;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.TaskInfo;
|
||||
@@ -51,8 +52,11 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.splitscreen.SplitScreenController;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Implementation of transitions for PiP on phone. Responsible for enter (alpha, bounds) and
|
||||
* exit animation.
|
||||
@@ -64,6 +68,7 @@ public class PipTransition extends PipTransitionController {
|
||||
private final PipTransitionState mPipTransitionState;
|
||||
private final int mEnterExitAnimationDuration;
|
||||
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
|
||||
private final Optional<SplitScreenController> mSplitScreenOptional;
|
||||
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
|
||||
private Transitions.TransitionFinishCallback mFinishCallback;
|
||||
private Rect mExitDestinationBounds = new Rect();
|
||||
@@ -77,13 +82,15 @@ public class PipTransition extends PipTransitionController {
|
||||
PipAnimationController pipAnimationController,
|
||||
Transitions transitions,
|
||||
@NonNull ShellTaskOrganizer shellTaskOrganizer,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper) {
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
Optional<SplitScreenController> splitScreenOptional) {
|
||||
super(pipBoundsState, pipMenuController, pipBoundsAlgorithm,
|
||||
pipAnimationController, transitions, shellTaskOrganizer);
|
||||
mPipTransitionState = pipTransitionState;
|
||||
mEnterExitAnimationDuration = context.getResources()
|
||||
.getInteger(R.integer.config_pipResizeAnimationDuration);
|
||||
mSurfaceTransactionHelper = pipSurfaceTransactionHelper;
|
||||
mSplitScreenOptional = splitScreenOptional;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,13 +108,12 @@ public class PipTransition extends PipTransitionController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTransition(Rect destinationBounds, WindowContainerTransaction out) {
|
||||
public void startExitTransition(int type, WindowContainerTransaction out,
|
||||
@Nullable Rect destinationBounds) {
|
||||
if (destinationBounds != null) {
|
||||
mExitDestinationBounds.set(destinationBounds);
|
||||
mExitTransition = mTransitions.startTransition(TRANSIT_EXIT_PIP, out, this);
|
||||
} else {
|
||||
mTransitions.startTransition(TRANSIT_REMOVE_PIP, out, this);
|
||||
}
|
||||
mExitTransition = mTransitions.startTransition(type, out, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,9 +122,15 @@ public class PipTransition extends PipTransitionController {
|
||||
@android.annotation.NonNull SurfaceControl.Transaction startTransaction,
|
||||
@android.annotation.NonNull SurfaceControl.Transaction finishTransaction,
|
||||
@android.annotation.NonNull Transitions.TransitionFinishCallback finishCallback) {
|
||||
|
||||
if (mExitTransition == transition || info.getType() == TRANSIT_EXIT_PIP) {
|
||||
final int type = info.getType();
|
||||
if (mExitTransition == transition) {
|
||||
mExitTransition = null;
|
||||
|
||||
if (type == TRANSIT_EXIT_PIP_TO_SPLIT) {
|
||||
return startExitToSplitAnimation(
|
||||
info, startTransaction, finishTransaction, finishCallback);
|
||||
}
|
||||
|
||||
if (info.getChanges().size() == 1) {
|
||||
if (mFinishCallback != null) {
|
||||
mFinishCallback.onTransitionFinished(null, null);
|
||||
@@ -138,7 +150,7 @@ public class PipTransition extends PipTransitionController {
|
||||
}
|
||||
}
|
||||
|
||||
if (info.getType() == TRANSIT_REMOVE_PIP) {
|
||||
if (type == TRANSIT_REMOVE_PIP) {
|
||||
if (mFinishCallback != null) {
|
||||
mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
|
||||
mFinishCallback = null;
|
||||
@@ -154,7 +166,7 @@ public class PipTransition extends PipTransitionController {
|
||||
|
||||
// We only support TRANSIT_PIP type (from RootWindowContainer) or TRANSIT_OPEN (from apps
|
||||
// that enter PiP instantly on opening, mostly from CTS/Flicker tests)
|
||||
if (info.getType() != TRANSIT_PIP && info.getType() != TRANSIT_OPEN) {
|
||||
if (type != TRANSIT_PIP && type != TRANSIT_OPEN) {
|
||||
// In case the PIP window is part of rotation transition, reset the bounds and rounded
|
||||
// corner.
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
@@ -368,6 +380,40 @@ public class PipTransition extends PipTransitionController {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean startExitToSplitAnimation(TransitionInfo info,
|
||||
SurfaceControl.Transaction startTransaction,
|
||||
SurfaceControl.Transaction finishTransaction,
|
||||
Transitions.TransitionFinishCallback finishCallback) {
|
||||
final int changeSize = info.getChanges().size();
|
||||
if (changeSize < 4) {
|
||||
throw new RuntimeException(
|
||||
"Got an exit-pip-to-split transition with unexpected change-list");
|
||||
}
|
||||
for (int i = changeSize - 1; i >= 0; i--) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
final int mode = change.getMode();
|
||||
|
||||
if (mode == TRANSIT_CHANGE && change.getParent() != null) {
|
||||
// TODO: perform resize/expand animation for reparented child task.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isOpeningType(mode) && change.getParent() == null) {
|
||||
final SurfaceControl leash = change.getLeash();
|
||||
final Rect endBounds = change.getEndAbsBounds();
|
||||
startTransaction
|
||||
.show(leash)
|
||||
.setAlpha(leash, 1f)
|
||||
.setPosition(leash, endBounds.left, endBounds.top)
|
||||
.setWindowCrop(leash, endBounds.width(), endBounds.height());
|
||||
}
|
||||
}
|
||||
mSplitScreenOptional.get().finishEnterSplitScreen(startTransaction);
|
||||
startTransaction.apply();
|
||||
finishCallback.onTransitionFinished(null, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void finishResizeForMenu(Rect destinationBounds) {
|
||||
mPipMenuController.movePipMenu(null, null, destinationBounds);
|
||||
mPipMenuController.updateMenuBounds(destinationBounds);
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
|
||||
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.PictureInPictureParams;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.ComponentName;
|
||||
@@ -98,9 +99,10 @@ public abstract class PipTransitionController implements Transitions.TransitionH
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Shell wants to starts a transition/animation.
|
||||
* Called when the Shell wants to start an exit Pip transition/animation.
|
||||
*/
|
||||
public void startTransition(Rect destinationBounds, WindowContainerTransaction out) {
|
||||
public void startExitTransition(int type, WindowContainerTransaction out,
|
||||
@Nullable Rect destinationBounds) {
|
||||
// Default implementation does nothing.
|
||||
}
|
||||
|
||||
|
||||
@@ -239,6 +239,15 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction());
|
||||
}
|
||||
|
||||
public void prepareEnterSplitScreen(WindowContainerTransaction wct,
|
||||
ActivityManager.RunningTaskInfo taskInfo, int startPosition) {
|
||||
mStageCoordinator.prepareEnterSplitScreen(wct, taskInfo, startPosition);
|
||||
}
|
||||
|
||||
public void finishEnterSplitScreen(SurfaceControl.Transaction t) {
|
||||
mStageCoordinator.finishEnterSplitScreen(t);
|
||||
}
|
||||
|
||||
public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) {
|
||||
final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE;
|
||||
final int stagePosition =
|
||||
|
||||
@@ -28,7 +28,8 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON
|
||||
import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS_SNAP;
|
||||
import static com.android.wm.shell.transition.Transitions.isOpeningType;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -148,7 +149,7 @@ class SplitScreenTransitions {
|
||||
t.setWindowCrop(leash, change.getEndAbsBounds().width(),
|
||||
change.getEndAbsBounds().height());
|
||||
}
|
||||
boolean isOpening = isOpeningType(info.getType());
|
||||
boolean isOpening = isOpeningTransition(info);
|
||||
if (isOpening && (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
|
||||
// fade in
|
||||
startExampleAnimation(leash, true /* show */);
|
||||
@@ -305,6 +306,12 @@ class SplitScreenTransitions {
|
||||
mTransitions.getAnimExecutor().execute(va::start);
|
||||
}
|
||||
|
||||
private boolean isOpeningTransition(TransitionInfo info) {
|
||||
return Transitions.isOpeningType(info.getType())
|
||||
|| info.getType() == TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE
|
||||
|| info.getType() == TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
|
||||
}
|
||||
|
||||
/** Bundled information of dismiss transition. */
|
||||
static class DismissTransition {
|
||||
IBinder mTransition;
|
||||
|
||||
@@ -46,6 +46,7 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON
|
||||
import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString;
|
||||
import static com.android.wm.shell.splitscreen.SplitScreenTransitions.FLAG_IS_DIVIDER_BAR;
|
||||
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE;
|
||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
|
||||
import static com.android.wm.shell.transition.Transitions.isClosingType;
|
||||
import static com.android.wm.shell.transition.Transitions.isOpeningType;
|
||||
@@ -323,7 +324,14 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
if (!evictWct.isEmpty()) {
|
||||
wct.merge(evictWct, true /* transfer */);
|
||||
}
|
||||
mTaskOrganizer.applyTransaction(wct);
|
||||
|
||||
if (ENABLE_SHELL_TRANSITIONS) {
|
||||
prepareEnterSplitScreen(wct);
|
||||
mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE,
|
||||
wct, null, this);
|
||||
} else {
|
||||
mTaskOrganizer.applyTransaction(wct);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -720,12 +728,47 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
* an existing WindowContainerTransaction (rather than applying immediately). This is intended
|
||||
* to be used when exiting split might be bundled with other window operations.
|
||||
*/
|
||||
void prepareExitSplitScreen(@StageType int stageToTop,
|
||||
private void prepareExitSplitScreen(@StageType int stageToTop,
|
||||
@NonNull WindowContainerTransaction wct) {
|
||||
if (!mMainStage.isActive()) return;
|
||||
mSideStage.removeAllTasks(wct, stageToTop == STAGE_TYPE_SIDE);
|
||||
mMainStage.deactivate(wct, stageToTop == STAGE_TYPE_MAIN);
|
||||
}
|
||||
|
||||
private void prepareEnterSplitScreen(WindowContainerTransaction wct) {
|
||||
prepareEnterSplitScreen(wct, null /* taskInfo */, SPLIT_POSITION_UNDEFINED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare transaction to active split screen. If there's a task indicated, the task will be put
|
||||
* into side stage.
|
||||
*/
|
||||
void prepareEnterSplitScreen(WindowContainerTransaction wct,
|
||||
@Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) {
|
||||
if (mMainStage.isActive()) return;
|
||||
|
||||
if (taskInfo != null) {
|
||||
setSideStagePosition(startPosition, wct);
|
||||
mSideStage.addTask(taskInfo, wct);
|
||||
}
|
||||
mMainStage.activate(getMainStageBounds(), wct, true /* includingTopTask */);
|
||||
mSideStage.moveToTop(getSideStageBounds(), wct);
|
||||
}
|
||||
|
||||
void finishEnterSplitScreen(SurfaceControl.Transaction t) {
|
||||
mSplitLayout.init();
|
||||
setDividerVisibility(true, t);
|
||||
setSplitsVisible(true);
|
||||
mShouldUpdateRecents = true;
|
||||
updateRecentTasksSplitPair();
|
||||
if (!mLogger.hasStartedSession()) {
|
||||
mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
|
||||
getMainStagePosition(), mMainStage.getTopChildTaskUid(),
|
||||
getSideStagePosition(), mSideStage.getTopChildTaskUid(),
|
||||
mSplitLayout.isLandscape());
|
||||
}
|
||||
}
|
||||
|
||||
void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
|
||||
outTopOrLeftBounds.set(mSplitLayout.getBounds1());
|
||||
outBottomOrRightBounds.set(mSplitLayout.getBounds2());
|
||||
@@ -932,8 +975,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mSplitLayout.init();
|
||||
// Make sure the main stage is active.
|
||||
mMainStage.activate(getMainStageBounds(), wct, true /* reparent */);
|
||||
mSideStage.moveToTop(getSideStageBounds(), wct);
|
||||
prepareEnterSplitScreen(wct);
|
||||
mSyncQueue.queue(wct);
|
||||
mSyncQueue.runInSync(t -> {
|
||||
updateSurfaceBounds(mSplitLayout, t);
|
||||
@@ -1237,8 +1279,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
if (isOpening && getStageOfTask(triggerTask) != null) {
|
||||
// One task is appearing into split, prepare to enter split screen.
|
||||
out = new WindowContainerTransaction();
|
||||
mMainStage.activate(getMainStageBounds(), out, true /* includingTopTask */);
|
||||
mSideStage.moveToTop(getSideStageBounds(), out);
|
||||
prepareEnterSplitScreen(out);
|
||||
mSplitTransitions.mPendingEnter = transition;
|
||||
}
|
||||
}
|
||||
@@ -1250,18 +1291,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
// Once the pending enter transition got merged, make sure to bring divider bar visible and
|
||||
// clear the pending transition from cache to prevent mess-up the following state.
|
||||
if (transition == mSplitTransitions.mPendingEnter) {
|
||||
mSplitLayout.init();
|
||||
setDividerVisibility(true, null /* transaction */);
|
||||
setSplitsVisible(true);
|
||||
mShouldUpdateRecents = true;
|
||||
updateRecentTasksSplitPair();
|
||||
|
||||
if (!mLogger.hasStartedSession()) {
|
||||
mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
|
||||
getMainStagePosition(), mMainStage.getTopChildTaskUid(),
|
||||
getSideStagePosition(), mSideStage.getTopChildTaskUid(),
|
||||
mSplitLayout.isLandscape());
|
||||
}
|
||||
finishEnterSplitScreen(null);
|
||||
mSplitTransitions.mPendingEnter = null;
|
||||
}
|
||||
}
|
||||
@@ -1349,47 +1379,40 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
sideChild = change;
|
||||
}
|
||||
}
|
||||
if (mainChild == null || sideChild == null) {
|
||||
throw new IllegalStateException("Launched 2 tasks in split, but didn't receive"
|
||||
+ " 2 tasks in transition. Possibly one of them failed to launch");
|
||||
// TODO: fallback logic. Probably start a new transition to exit split before
|
||||
// applying anything here. Ideally consolidate with transition-merging.
|
||||
|
||||
// TODO: fallback logic. Probably start a new transition to exit split before applying
|
||||
// anything here. Ideally consolidate with transition-merging.
|
||||
if (info.getType() == TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE) {
|
||||
if (mainChild == null && sideChild == null) {
|
||||
throw new IllegalStateException("Launched a task in split, but didn't receive any"
|
||||
+ " task in transition.");
|
||||
}
|
||||
} else {
|
||||
if (mainChild == null || sideChild == null) {
|
||||
throw new IllegalStateException("Launched 2 tasks in split, but didn't receive"
|
||||
+ " 2 tasks in transition. Possibly one of them failed to launch");
|
||||
}
|
||||
}
|
||||
|
||||
// Update local states (before animating).
|
||||
mSplitLayout.init();
|
||||
setDividerVisibility(true, t);
|
||||
setSplitsVisible(true);
|
||||
|
||||
addDividerBarToTransition(info, t, true /* show */);
|
||||
|
||||
// Make some noise if things aren't totally expected. These states shouldn't effect
|
||||
// transitions locally, but remotes (like Launcher) may get confused if they were
|
||||
// depending on listener callbacks. This can happen because task-organizer callbacks
|
||||
// aren't serialized with transition callbacks.
|
||||
// TODO(b/184679596): Find a way to either include task-org information in
|
||||
// the transition, or synchronize task-org callbacks.
|
||||
if (!mMainStage.containsTask(mainChild.getTaskInfo().taskId)) {
|
||||
if (mainChild != null && !mMainStage.containsTask(mainChild.getTaskInfo().taskId)) {
|
||||
Log.w(TAG, "Expected onTaskAppeared on " + mMainStage
|
||||
+ " to have been called with " + mainChild.getTaskInfo().taskId
|
||||
+ " before startAnimation().");
|
||||
}
|
||||
if (!mSideStage.containsTask(sideChild.getTaskInfo().taskId)) {
|
||||
if (sideChild != null && !mSideStage.containsTask(sideChild.getTaskInfo().taskId)) {
|
||||
Log.w(TAG, "Expected onTaskAppeared on " + mSideStage
|
||||
+ " to have been called with " + sideChild.getTaskInfo().taskId
|
||||
+ " before startAnimation().");
|
||||
}
|
||||
|
||||
mShouldUpdateRecents = true;
|
||||
updateRecentTasksSplitPair();
|
||||
|
||||
if (!mLogger.hasStartedSession()) {
|
||||
mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
|
||||
getMainStagePosition(), mMainStage.getTopChildTaskUid(),
|
||||
getSideStagePosition(), mSideStage.getTopChildTaskUid(),
|
||||
mSplitLayout.isLandscape());
|
||||
}
|
||||
|
||||
finishEnterSplitScreen(t);
|
||||
addDividerBarToTransition(info, t, true /* show */);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -302,6 +302,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
}
|
||||
|
||||
void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) {
|
||||
// Clear overridden bounds and windowing mode to make sure the child task can inherit
|
||||
// windowing mode and bounds from split root.
|
||||
wct.setWindowingMode(task.token, WINDOWING_MODE_UNDEFINED)
|
||||
.setBounds(task.token, null);
|
||||
|
||||
wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,23 +74,25 @@ public class Transitions implements RemoteCallable<Transitions> {
|
||||
public static final boolean ENABLE_SHELL_TRANSITIONS =
|
||||
SystemProperties.getBoolean("persist.debug.shell_transit", false);
|
||||
|
||||
/** Transition type for dismissing split-screen via dragging the divider off the screen. */
|
||||
public static final int TRANSIT_SPLIT_DISMISS_SNAP = TRANSIT_FIRST_CUSTOM + 1;
|
||||
|
||||
/** Transition type for launching 2 tasks simultaneously. */
|
||||
public static final int TRANSIT_SPLIT_SCREEN_PAIR_OPEN = TRANSIT_FIRST_CUSTOM + 2;
|
||||
|
||||
/** Transition type for exiting PIP via the Shell, via pressing the expand button. */
|
||||
public static final int TRANSIT_EXIT_PIP = TRANSIT_FIRST_CUSTOM + 3;
|
||||
public static final int TRANSIT_EXIT_PIP = TRANSIT_FIRST_CUSTOM + 1;
|
||||
|
||||
public static final int TRANSIT_EXIT_PIP_TO_SPLIT = TRANSIT_FIRST_CUSTOM + 2;
|
||||
|
||||
/** Transition type for removing PIP via the Shell, either via Dismiss bubble or Close. */
|
||||
public static final int TRANSIT_REMOVE_PIP = TRANSIT_FIRST_CUSTOM + 4;
|
||||
public static final int TRANSIT_REMOVE_PIP = TRANSIT_FIRST_CUSTOM + 3;
|
||||
|
||||
/** Transition type for launching 2 tasks simultaneously. */
|
||||
public static final int TRANSIT_SPLIT_SCREEN_PAIR_OPEN = TRANSIT_FIRST_CUSTOM + 4;
|
||||
|
||||
/** Transition type for entering split by opening an app into side-stage. */
|
||||
public static final int TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE = TRANSIT_FIRST_CUSTOM + 5;
|
||||
|
||||
/** Transition type for dismissing split-screen via dragging the divider off the screen. */
|
||||
public static final int TRANSIT_SPLIT_DISMISS_SNAP = TRANSIT_FIRST_CUSTOM + 6;
|
||||
|
||||
/** Transition type for dismissing split-screen. */
|
||||
public static final int TRANSIT_SPLIT_DISMISS = TRANSIT_FIRST_CUSTOM + 6;
|
||||
public static final int TRANSIT_SPLIT_DISMISS = TRANSIT_FIRST_CUSTOM + 7;
|
||||
|
||||
private final WindowOrganizer mOrganizer;
|
||||
private final Context mContext;
|
||||
|
||||
Reference in New Issue
Block a user