Merge "Consolidate drag to split gesture with shell transition" into tm-qpr-dev

This commit is contained in:
Jerry Chang
2022-07-27 02:15:57 +00:00
committed by Android (Google) Code Review
4 changed files with 222 additions and 122 deletions

View File

@@ -352,41 +352,31 @@ 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) { @SplitPosition int position, @Nullable Bundle options) {
if (fillInIntent == null) {
fillInIntent = new Intent();
}
// Flag this as a no-user-action launch to prevent sending user leaving event to the
// current top activity since it's going to be put into another side of the split. This
// prevents the current top activity from going into pip mode due to user leaving event.
fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
// Flag with MULTIPLE_TASK if this is launching the same activity into both sides of the
// split.
if (isLaunchingAdjacently(intent.getIntent(), position)) {
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
}
if (!ENABLE_SHELL_TRANSITIONS) { if (!ENABLE_SHELL_TRANSITIONS) {
startIntentLegacy(intent, fillInIntent, position, options); startIntentLegacy(intent, fillInIntent, position, options);
return; return;
} }
try { mStageCoordinator.startIntent(intent, fillInIntent, position, options);
options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
null /* wct */);
if (fillInIntent == null) {
fillInIntent = new Intent();
}
// Flag this as a no-user-action launch to prevent sending user leaving event to the
// current top activity since it's going to be put into another side of the split. This
// prevents the current top activity from going into pip mode due to user leaving event.
fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
// Flag with MULTIPLE_TASK if this is launching the same activity into both sides of the
// split.
if (isLaunchingAdjacently(intent.getIntent(), position)) {
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
}
intent.send(mContext, 0, fillInIntent, null /* onFinished */, null /* handler */,
null /* requiredPermission */, options);
} catch (PendingIntent.CanceledException e) {
Slog.e(TAG, "Failed to launch task", e);
}
} }
private void startIntentLegacy(PendingIntent intent, @Nullable Intent fillInIntent, private void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
@SplitPosition int position, @Nullable Bundle options) { @SplitPosition int position, @Nullable Bundle options) {
boolean startSameActivityAdjacently = isLaunchingAdjacently(intent.getIntent(), position);
final WindowContainerTransaction evictWct = new WindowContainerTransaction(); final WindowContainerTransaction evictWct = new WindowContainerTransaction();
mStageCoordinator.prepareEvictChildTasks(position, evictWct); mStageCoordinator.prepareEvictChildTasks(position, evictWct);
@@ -397,8 +387,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
IRemoteAnimationFinishedCallback finishedCallback, IRemoteAnimationFinishedCallback finishedCallback,
SurfaceControl.Transaction t) { SurfaceControl.Transaction t) {
if (apps == null || apps.length == 0) { if (apps == null || apps.length == 0) {
if (startSameActivityAdjacently) { // Switch the split position if launching as MULTIPLE_TASK failed.
// Switch split position if dragging the same activity to another side. if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
setSideStagePosition(SplitLayout.reversePosition( setSideStagePosition(SplitLayout.reversePosition(
mStageCoordinator.getSideStagePosition())); mStageCoordinator.getSideStagePosition()));
} }
@@ -432,18 +422,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
final WindowContainerTransaction wct = new WindowContainerTransaction(); final WindowContainerTransaction wct = new WindowContainerTransaction();
options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct); options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct);
// Flag this as a no-user-action launch to prevent sending user leaving event to the current
// top activity since it's going to be put into another side of the split. This prevents the
// current top activity from going into pip mode due to user leaving event.
if (fillInIntent == null) {
fillInIntent = new Intent();
}
fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
if (startSameActivityAdjacently) {
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
}
wct.sendPendingIntent(intent, fillInIntent, options); wct.sendPendingIntent(intent, fillInIntent, options);
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct); mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
} }

View File

@@ -62,13 +62,12 @@ class SplitScreenTransitions {
private final Runnable mOnFinish; private final Runnable mOnFinish;
DismissTransition mPendingDismiss = null; DismissTransition mPendingDismiss = null;
IBinder mPendingEnter = null; TransitSession mPendingEnter = null;
IBinder mPendingRecent = null; TransitSession mPendingRecent = null;
private IBinder mAnimatingTransition = null; private IBinder mAnimatingTransition = null;
OneShotRemoteHandler mPendingRemoteHandler = null; OneShotRemoteHandler mPendingRemoteHandler = null;
private OneShotRemoteHandler mActiveRemoteHandler = null; private OneShotRemoteHandler mActiveRemoteHandler = null;
private boolean mEnterTransitionMerged;
private final Transitions.TransitionFinishCallback mRemoteFinishCB = this::onFinish; private final Transitions.TransitionFinishCallback mRemoteFinishCB = this::onFinish;
@@ -145,7 +144,7 @@ class SplitScreenTransitions {
continue; continue;
} }
if (transition == mPendingEnter && (mainRoot.equals(change.getContainer()) if (isPendingEnter(transition) && (mainRoot.equals(change.getContainer())
|| sideRoot.equals(change.getContainer()))) { || sideRoot.equals(change.getContainer()))) {
t.setPosition(leash, change.getEndAbsBounds().left, change.getEndAbsBounds().top); t.setPosition(leash, change.getEndAbsBounds().left, change.getEndAbsBounds().top);
t.setWindowCrop(leash, change.getEndAbsBounds().width(), t.setWindowCrop(leash, change.getEndAbsBounds().width(),
@@ -171,12 +170,40 @@ class SplitScreenTransitions {
onFinish(null /* wct */, null /* wctCB */); onFinish(null /* wct */, null /* wctCB */);
} }
boolean isPendingTransition(IBinder transition) {
return isPendingEnter(transition)
|| isPendingDismiss(transition)
|| isPendingRecent(transition);
}
boolean isPendingEnter(IBinder transition) {
return mPendingEnter != null && mPendingEnter.mTransition == transition;
}
boolean isPendingRecent(IBinder transition) {
return mPendingRecent != null && mPendingRecent.mTransition == transition;
}
boolean isPendingDismiss(IBinder transition) {
return mPendingDismiss != null && mPendingDismiss.mTransition == transition;
}
/** Starts a transition to enter split with a remote transition animator. */ /** Starts a transition to enter split with a remote transition animator. */
IBinder startEnterTransition(@WindowManager.TransitionType int transitType, IBinder startEnterTransition(
@NonNull WindowContainerTransaction wct, @Nullable RemoteTransition remoteTransition, @WindowManager.TransitionType int transitType,
@NonNull Transitions.TransitionHandler handler) { WindowContainerTransaction wct,
@Nullable RemoteTransition remoteTransition,
Transitions.TransitionHandler handler,
@Nullable TransitionCallback callback) {
final IBinder transition = mTransitions.startTransition(transitType, wct, handler); final IBinder transition = mTransitions.startTransition(transitType, wct, handler);
mPendingEnter = transition; setEnterTransition(transition, remoteTransition, callback);
return transition;
}
/** Sets a transition to enter split. */
void setEnterTransition(@NonNull IBinder transition,
@Nullable RemoteTransition remoteTransition, @Nullable TransitionCallback callback) {
mPendingEnter = new TransitSession(transition, callback);
if (remoteTransition != null) { if (remoteTransition != null) {
// Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff) // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
@@ -184,7 +211,9 @@ class SplitScreenTransitions {
mTransitions.getMainExecutor(), remoteTransition); mTransitions.getMainExecutor(), remoteTransition);
mPendingRemoteHandler.setTransition(transition); mPendingRemoteHandler.setTransition(transition);
} }
return transition;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " splitTransition "
+ " deduced Enter split screen");
} }
/** Starts a transition to dismiss split. */ /** Starts a transition to dismiss split. */
@@ -209,8 +238,8 @@ class SplitScreenTransitions {
} }
void setRecentTransition(@NonNull IBinder transition, void setRecentTransition(@NonNull IBinder transition,
@Nullable RemoteTransition remoteTransition) { @Nullable RemoteTransition remoteTransition, @Nullable TransitionCallback callback) {
mPendingRecent = transition; mPendingRecent = new TransitSession(transition, callback);
if (remoteTransition != null) { if (remoteTransition != null) {
// Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff) // Wrapping it for ease-of-use (OneShot handles all the binder linking/death stuff)
@@ -226,6 +255,18 @@ class SplitScreenTransitions {
void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t, void mergeAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) { IBinder mergeTarget, Transitions.TransitionFinishCallback finishCallback) {
if (mergeTarget != mAnimatingTransition) return; if (mergeTarget != mAnimatingTransition) return;
if (isPendingEnter(transition) && isPendingRecent(mergeTarget)) {
mPendingRecent.mCallback = new TransitionCallback() {
@Override
public void onTransitionFinished(WindowContainerTransaction finishWct,
SurfaceControl.Transaction finishT) {
// Since there's an entering transition merged, recent transition no longer
// need to handle entering split screen after the transition finished.
}
};
}
if (mActiveRemoteHandler != null) { if (mActiveRemoteHandler != null) {
mActiveRemoteHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback); mActiveRemoteHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
} else { } else {
@@ -247,38 +288,55 @@ class SplitScreenTransitions {
} }
void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) { void onTransitionConsumed(@NonNull IBinder transition, boolean aborted) {
if (aborted) return; if (isPendingEnter(transition)) {
if (!aborted) {
// An enter transition got merged, appends the rest operations to finish entering
// split screen.
// TODO (b/238856352): Passed-in the proper finish transition to merge instead.
if (mFinishTransaction == null) {
mFinishTransaction = mTransactionPool.acquire();
}
mStageCoordinator.finishEnterSplitScreen(mFinishTransaction);
}
// Once a pending enter transition got merged, make sure to append the reset of finishing mPendingEnter.mCallback.onTransitionConsumed(aborted);
// operations to the finish transition.
if (transition == mPendingEnter) {
mFinishTransaction = mTransactionPool.acquire();
mStageCoordinator.finishEnterSplitScreen(mFinishTransaction);
mPendingEnter = null; mPendingEnter = null;
mPendingRemoteHandler = null; mPendingRemoteHandler = null;
mEnterTransitionMerged = true; } else if (isPendingDismiss(transition)) {
mPendingDismiss.mCallback.onTransitionConsumed(aborted);
mPendingDismiss = null;
} else if (isPendingRecent(transition)) {
mPendingRecent.mCallback.onTransitionConsumed(aborted);
mPendingRecent = null;
mPendingRemoteHandler = null;
} }
} }
void onFinish(WindowContainerTransaction wct, WindowContainerTransactionCallback wctCB) { void onFinish(WindowContainerTransaction wct, WindowContainerTransactionCallback wctCB) {
if (!mAnimations.isEmpty()) return; if (!mAnimations.isEmpty()) return;
if (mAnimatingTransition == mPendingEnter) {
TransitionCallback callback = null;
if (isPendingEnter(mAnimatingTransition)) {
callback = mPendingEnter.mCallback;
mPendingEnter = null; mPendingEnter = null;
} }
if (mPendingDismiss != null && mPendingDismiss.mTransition == mAnimatingTransition) { if (isPendingDismiss(mAnimatingTransition)) {
callback = mPendingDismiss.mCallback;
mPendingDismiss = null; mPendingDismiss = null;
} }
if (mAnimatingTransition == mPendingRecent) { if (isPendingRecent(mAnimatingTransition)) {
if (!mEnterTransitionMerged) { callback = mPendingRecent.mCallback;
if (wct == null) wct = new WindowContainerTransaction();
mStageCoordinator.onRecentTransitionFinished(wct, mFinishTransaction);
}
mPendingRecent = null; mPendingRecent = null;
} }
if (callback != null) {
if (wct == null) wct = new WindowContainerTransaction();
callback.onTransitionFinished(wct, mFinishTransaction);
}
mPendingRemoteHandler = null; mPendingRemoteHandler = null;
mActiveRemoteHandler = null; mActiveRemoteHandler = null;
mAnimatingTransition = null; mAnimatingTransition = null;
mEnterTransitionMerged = false;
mOnFinish.run(); mOnFinish.run();
if (mFinishTransaction != null) { if (mFinishTransaction != null) {
@@ -382,17 +440,34 @@ class SplitScreenTransitions {
|| info.getType() == TRANSIT_SPLIT_SCREEN_PAIR_OPEN; || info.getType() == TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
} }
/** Clean-up callbacks for transition. */
interface TransitionCallback {
/** Calls when the transition got consumed. */
default void onTransitionConsumed(boolean aborted) {}
/** Calls when the transition finished. */
default void onTransitionFinished(WindowContainerTransaction finishWct,
SurfaceControl.Transaction finishT) {}
}
/** Session for a transition and its clean-up callback. */
static class TransitSession {
final IBinder mTransition;
TransitionCallback mCallback;
TransitSession(IBinder transition, @Nullable TransitionCallback callback) {
mTransition = transition;
mCallback = callback != null ? callback : new TransitionCallback() {};
}
}
/** Bundled information of dismiss transition. */ /** Bundled information of dismiss transition. */
static class DismissTransition { static class DismissTransition extends TransitSession {
IBinder mTransition; final int mReason;
final @SplitScreen.StageType int mDismissTop;
int mReason;
@SplitScreen.StageType
int mDismissTop;
DismissTransition(IBinder transition, int reason, int dismissTop) { DismissTransition(IBinder transition, int reason, int dismissTop) {
this.mTransition = transition; super(transition, null /* callback */);
this.mReason = reason; this.mReason = reason;
this.mDismissTop = dismissTop; this.mDismissTop = dismissTop;
} }

View File

@@ -24,6 +24,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CHANGE;
@@ -214,6 +215,33 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
}; };
private final SplitScreenTransitions.TransitionCallback mRecentTransitionCallback =
new SplitScreenTransitions.TransitionCallback() {
@Override
public void onTransitionFinished(WindowContainerTransaction finishWct,
SurfaceControl.Transaction finishT) {
// Check if the recent transition is finished by returning to the current split, so we
// can restore the divider bar.
for (int i = 0; i < finishWct.getHierarchyOps().size(); ++i) {
final WindowContainerTransaction.HierarchyOp op =
finishWct.getHierarchyOps().get(i);
final IBinder container = op.getContainer();
if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
&& (mMainStage.containsContainer(container)
|| mSideStage.containsContainer(container))) {
setDividerVisibility(true, finishT);
return;
}
}
// Dismiss the split screen if it's not returning to split.
prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, finishWct);
setSplitsVisible(false);
setDividerVisibility(false, finishT);
logExit(EXIT_REASON_UNKNOWN);
}
};
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
ShellTaskOrganizer taskOrganizer, DisplayController displayController, ShellTaskOrganizer taskOrganizer, DisplayController displayController,
DisplayImeController displayImeController, DisplayImeController displayImeController,
@@ -337,15 +365,23 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction evictWct = new WindowContainerTransaction(); final WindowContainerTransaction evictWct = new WindowContainerTransaction();
targetStage.evictAllChildren(evictWct); targetStage.evictAllChildren(evictWct);
targetStage.addTask(task, wct); targetStage.addTask(task, wct);
if (!evictWct.isEmpty()) {
wct.merge(evictWct, true /* transfer */);
}
if (ENABLE_SHELL_TRANSITIONS) { if (ENABLE_SHELL_TRANSITIONS) {
prepareEnterSplitScreen(wct); prepareEnterSplitScreen(wct);
mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct,
wct, null, this); null, this, new SplitScreenTransitions.TransitionCallback() {
@Override
public void onTransitionFinished(WindowContainerTransaction finishWct,
SurfaceControl.Transaction finishT) {
if (!evictWct.isEmpty()) {
finishWct.merge(evictWct, true);
}
}
});
} else { } else {
if (!evictWct.isEmpty()) {
wct.merge(evictWct, true /* transfer */);
}
mTaskOrganizer.applyTransaction(wct); mTaskOrganizer.applyTransaction(wct);
} }
return true; return true;
@@ -365,6 +401,39 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return result; return result;
} }
/** Launches an activity into split. */
void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
@Nullable Bundle options) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
prepareEvictChildTasks(position, evictWct);
options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, null /* wct */);
wct.sendPendingIntent(intent, fillInIntent, options);
prepareEnterSplitScreen(wct, null /* taskInfo */, position);
mSplitTransitions.startEnterTransition(TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct, null, this,
new SplitScreenTransitions.TransitionCallback() {
@Override
public void onTransitionConsumed(boolean aborted) {
// Switch the split position if launching as MULTIPLE_TASK failed.
if (aborted
&& (fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
setSideStagePositionAnimated(
SplitLayout.reversePosition(mSideStagePosition));
}
}
@Override
public void onTransitionFinished(WindowContainerTransaction finishWct,
SurfaceControl.Transaction finishT) {
if (!evictWct.isEmpty()) {
finishWct.merge(evictWct, true);
}
}
});
}
/** Starts 2 tasks in one transition. */ /** Starts 2 tasks in one transition. */
void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId,
@Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio,
@@ -395,7 +464,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
wct.startTask(sideTaskId, sideOptions); wct.startTask(sideTaskId, sideOptions);
mSplitTransitions.startEnterTransition( mSplitTransitions.startEnterTransition(
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this); TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this, null);
} }
/** Starts 2 tasks in one legacy transition. */ /** Starts 2 tasks in one legacy transition. */
@@ -617,11 +686,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
int getTaskId(@SplitPosition int splitPosition) { int getTaskId(@SplitPosition int splitPosition) {
if (mSideStagePosition == splitPosition) { if (splitPosition == SPLIT_POSITION_UNDEFINED) {
return mSideStage.getTopVisibleChildTaskId(); return INVALID_TASK_ID;
} else {
return mMainStage.getTopVisibleChildTaskId();
} }
return mSideStagePosition == splitPosition
? mSideStage.getTopVisibleChildTaskId()
: mMainStage.getTopVisibleChildTaskId();
} }
void setSideStagePositionAnimated(@SplitPosition int sideStagePosition) { void setSideStagePositionAnimated(@SplitPosition int sideStagePosition) {
@@ -861,6 +932,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout.init(); mSplitLayout.init();
setDividerVisibility(true, t); setDividerVisibility(true, t);
updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
t.show(mRootTaskLeash);
setSplitsVisible(true); setSplitsVisible(true);
mShouldUpdateRecents = true; mShouldUpdateRecents = true;
updateRecentTasksSplitPair(); updateRecentTasksSplitPair();
@@ -1543,14 +1615,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} else if (activityType == ACTIVITY_TYPE_HOME } else if (activityType == ACTIVITY_TYPE_HOME
|| activityType == ACTIVITY_TYPE_RECENTS) { || activityType == ACTIVITY_TYPE_RECENTS) {
// Enter overview panel, so start recent transition. // Enter overview panel, so start recent transition.
mSplitTransitions.setRecentTransition(transition, mSplitTransitions.setRecentTransition(transition, request.getRemoteTransition(),
request.getRemoteTransition()); mRecentTransitionCallback);
} else if (mSplitTransitions.mPendingRecent == null) { } else if (mSplitTransitions.mPendingRecent == null) {
// If split-task is not controlled by recents animation // If split-task is not controlled by recents animation
// and occluded by the other fullscreen task, dismiss both. // and occluded by the other fullscreen task, dismiss both.
prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out); prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out);
mSplitTransitions.setDismissTransition(transition, mSplitTransitions.setDismissTransition(
STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN); transition, STAGE_TYPE_UNDEFINED, EXIT_REASON_UNKNOWN);
} }
} }
} else { } else {
@@ -1558,7 +1630,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// One task is appearing into split, prepare to enter split screen. // One task is appearing into split, prepare to enter split screen.
out = new WindowContainerTransaction(); out = new WindowContainerTransaction();
prepareEnterSplitScreen(out); prepareEnterSplitScreen(out);
mSplitTransitions.mPendingEnter = transition; mSplitTransitions.setEnterTransition(
transition, request.getRemoteTransition(), null /* callback */);
} }
} }
return out; return out;
@@ -1614,10 +1687,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction, @NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) { @NonNull Transitions.TransitionFinishCallback finishCallback) {
if (transition != mSplitTransitions.mPendingEnter if (!mSplitTransitions.isPendingTransition(transition)) {
&& transition != mSplitTransitions.mPendingRecent
&& (mSplitTransitions.mPendingDismiss == null
|| mSplitTransitions.mPendingDismiss.mTransition != transition)) {
// Not entering or exiting, so just do some house-keeping and validation. // Not entering or exiting, so just do some house-keeping and validation.
// If we're not in split-mode, just abort so something else can handle it. // If we're not in split-mode, just abort so something else can handle it.
@@ -1664,12 +1734,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} }
boolean shouldAnimate = true; boolean shouldAnimate = true;
if (mSplitTransitions.mPendingEnter == transition) { if (mSplitTransitions.isPendingEnter(transition)) {
shouldAnimate = startPendingEnterAnimation(transition, info, startTransaction); shouldAnimate = startPendingEnterAnimation(transition, info, startTransaction);
} else if (mSplitTransitions.mPendingRecent == transition) { } else if (mSplitTransitions.isPendingRecent(transition)) {
shouldAnimate = startPendingRecentAnimation(transition, info, startTransaction); shouldAnimate = startPendingRecentAnimation(transition, info, startTransaction);
} else if (mSplitTransitions.mPendingDismiss != null } else if (mSplitTransitions.isPendingDismiss(transition)) {
&& mSplitTransitions.mPendingDismiss.mTransition == transition) {
shouldAnimate = startPendingDismissAnimation( shouldAnimate = startPendingDismissAnimation(
mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction); mSplitTransitions.mPendingDismiss, info, startTransaction, finishTransaction);
} }
@@ -1837,28 +1906,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return true; return true;
} }
void onRecentTransitionFinished(WindowContainerTransaction wct,
SurfaceControl.Transaction finishT) {
// Check if the recent transition is finished by returning to the current split so we can
// restore the divider bar.
for (int i = 0; i < wct.getHierarchyOps().size(); ++i) {
final WindowContainerTransaction.HierarchyOp op = wct.getHierarchyOps().get(i);
final IBinder container = op.getContainer();
if (op.getType() == HIERARCHY_OP_TYPE_REORDER && op.getToTop()
&& (mMainStage.containsContainer(container)
|| mSideStage.containsContainer(container))) {
setDividerVisibility(true, finishT);
return;
}
}
// Dismiss the split screen is it's not returning to split.
prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
setSplitsVisible(false);
setDividerVisibility(false, finishT);
logExit(EXIT_REASON_UNKNOWN);
}
private void addDividerBarToTransition(@NonNull TransitionInfo info, private void addDividerBarToTransition(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, boolean show) { @NonNull SurfaceControl.Transaction t, boolean show) {
final SurfaceControl leash = mSplitLayout.getDividerLeash(); final SurfaceControl leash = mSplitLayout.getDividerLeash();

View File

@@ -182,7 +182,7 @@ public class SplitTransitionTests extends ShellTestCase {
IBinder transition = mSplitScreenTransitions.startEnterTransition( IBinder transition = mSplitScreenTransitions.startEnterTransition(
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(), TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(),
new RemoteTransition(testRemote), mStageCoordinator); new RemoteTransition(testRemote), mStageCoordinator, null);
mMainStage.onTaskAppeared(mMainChild, createMockSurface()); mMainStage.onTaskAppeared(mMainChild, createMockSurface());
mSideStage.onTaskAppeared(mSideChild, createMockSurface()); mSideStage.onTaskAppeared(mSideChild, createMockSurface());
boolean accepted = mStageCoordinator.startAnimation(transition, info, boolean accepted = mStageCoordinator.startAnimation(transition, info,
@@ -422,7 +422,7 @@ public class SplitTransitionTests extends ShellTestCase {
TransitionInfo enterInfo = createEnterPairInfo(); TransitionInfo enterInfo = createEnterPairInfo();
IBinder enterTransit = mSplitScreenTransitions.startEnterTransition( IBinder enterTransit = mSplitScreenTransitions.startEnterTransition(
TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(), TRANSIT_SPLIT_SCREEN_PAIR_OPEN, new WindowContainerTransaction(),
new RemoteTransition(new TestRemoteTransition()), mStageCoordinator); new RemoteTransition(new TestRemoteTransition()), mStageCoordinator, null);
mMainStage.onTaskAppeared(mMainChild, createMockSurface()); mMainStage.onTaskAppeared(mMainChild, createMockSurface());
mSideStage.onTaskAppeared(mSideChild, createMockSurface()); mSideStage.onTaskAppeared(mSideChild, createMockSurface());
mStageCoordinator.startAnimation(enterTransit, enterInfo, mStageCoordinator.startAnimation(enterTransit, enterInfo,