Merge "Transfer PipContentOverlay when swipe to home with Shell transition" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-05 15:34:07 +00:00
committed by Android (Google) Code Review
12 changed files with 178 additions and 30 deletions

View File

@@ -98,16 +98,22 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
default void onTaskInfoChanged(RunningTaskInfo taskInfo) {} default void onTaskInfoChanged(RunningTaskInfo taskInfo) {}
default void onTaskVanished(RunningTaskInfo taskInfo) {} default void onTaskVanished(RunningTaskInfo taskInfo) {}
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {} default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {}
/** Whether this task listener supports compat UI. */ /** Whether this task listener supports compat UI. */
default boolean supportCompatUI() { default boolean supportCompatUI() {
// All TaskListeners should support compat UI except PIP. // All TaskListeners should support compat UI except PIP.
return true; return true;
} }
/** Attaches the a child window surface to the task surface. */ /** Attaches a child window surface to the task surface. */
default void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) { default void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
throw new IllegalStateException( throw new IllegalStateException(
"This task listener doesn't support child surface attachment."); "This task listener doesn't support child surface attachment.");
} }
/** Reparents a child window surface to the task surface. */
default void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
throw new IllegalStateException(
"This task listener doesn't support child surface reparent.");
}
default void dump(@NonNull PrintWriter pw, String prefix) {}; default void dump(@NonNull PrintWriter pw, String prefix) {};
} }
@@ -620,6 +626,23 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
updateCameraCompatControlState(info.getTaskInfo().token, state); updateCameraCompatControlState(info.getTaskInfo().token, state);
} }
/** Reparents a child window surface to the task surface. */
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
final TaskListener taskListener;
synchronized (mLock) {
taskListener = mTasks.contains(taskId)
? getTaskListener(mTasks.get(taskId).getTaskInfo())
: null;
}
if (taskListener == null) {
ProtoLog.w(WM_SHELL_TASK_ORG, "Failed to find Task to reparent surface taskId=%d",
taskId);
return;
}
taskListener.reparentChildSurfaceToTask(taskId, sc, t);
}
private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info, private void logSizeCompatRestartButtonEventReported(@NonNull TaskAppearedInfo info,
int event) { int event) {
ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo; ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo;

View File

@@ -367,10 +367,20 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
@Override @Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) { public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
if (mTaskInfo.taskId != taskId) { b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (mTaskInfo == null || mTaskLeash == null || mTaskInfo.taskId != taskId) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId); throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
} }
b.setParent(mTaskLeash); return mTaskLeash;
} }
@Override @Override

View File

@@ -275,12 +275,22 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou
@Override @Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) { public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (getRootTaskId() == taskId) { if (getRootTaskId() == taskId) {
b.setParent(mRootTaskLeash); return mRootTaskLeash;
} else if (getTaskId1() == taskId) { } else if (getTaskId1() == taskId) {
b.setParent(mTaskLeash1); return mTaskLeash1;
} else if (getTaskId2() == taskId) { } else if (getTaskId2() == taskId) {
b.setParent(mTaskLeash2); return mTaskLeash2;
} else { } else {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId); throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
} }

View File

@@ -109,6 +109,24 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener {
}); });
} }
@Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (!mTasks.contains(taskId)) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
}
return mTasks.get(taskId).mLeash;
}
@Override @Override
public void dump(PrintWriter pw, String prefix) { public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " "; final String innerPrefix = prefix + " ";

View File

@@ -133,10 +133,20 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
@Override @Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) { public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (!mDataByTaskId.contains(taskId)) { if (!mDataByTaskId.contains(taskId)) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId); throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
} }
b.setParent(mDataByTaskId.get(taskId).surface); return mDataByTaskId.get(taskId).surface;
} }
@Override @Override

View File

@@ -343,10 +343,20 @@ class LegacySplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
@Override @Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) { public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (!mLeashByTaskId.contains(taskId)) { if (!mLeashByTaskId.contains(taskId)) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId); throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
} }
b.setParent(mLeashByTaskId.get(taskId)); return mLeashByTaskId.get(taskId);
} }
@Override @Override

View File

@@ -47,12 +47,13 @@ interface IPip {
/** /**
* Notifies the swiping Activity to PiP onto home transition is finished * Notifies the swiping Activity to PiP onto home transition is finished
* *
* @param taskId the Task id that the Activity and overlay are currently in.
* @param componentName ComponentName represents the Activity * @param componentName ComponentName represents the Activity
* @param destinationBounds the destination bounds the PiP window lands into * @param destinationBounds the destination bounds the PiP window lands into
* @param overlay an optional overlay to fade out after entering PiP * @param overlay an optional overlay to fade out after entering PiP
*/ */
oneway void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds, oneway void stopSwipePipToHome(int taskId, in ComponentName componentName,
in SurfaceControl overlay) = 2; in Rect destinationBounds, in SurfaceControl overlay) = 2;
/** /**
* Sets listener to get pinned stack animation callbacks. * Sets listener to get pinned stack animation callbacks.

View File

@@ -250,7 +250,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
* An optional overlay used to mask content changing between an app in/out of PiP, only set if * An optional overlay used to mask content changing between an app in/out of PiP, only set if
* {@link PipTransitionState#getInSwipePipToHomeTransition()} is true. * {@link PipTransitionState#getInSwipePipToHomeTransition()} is true.
*/ */
private SurfaceControl mSwipePipToHomeOverlay; @Nullable
SurfaceControl mSwipePipToHomeOverlay;
public PipTaskOrganizer(Context context, public PipTaskOrganizer(Context context,
@NonNull SyncTransactionQueue syncTransactionQueue, @NonNull SyncTransactionQueue syncTransactionQueue,
@@ -357,12 +358,24 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
* Callback when launcher finishes swipe-pip-to-home operation. * Callback when launcher finishes swipe-pip-to-home operation.
* Expect {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)} afterwards. * Expect {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)} afterwards.
*/ */
public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, public void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds,
SurfaceControl overlay) { SurfaceControl overlay) {
// do nothing if there is no startSwipePipToHome being called before // do nothing if there is no startSwipePipToHome being called before
if (mPipTransitionState.getInSwipePipToHomeTransition()) { if (!mPipTransitionState.getInSwipePipToHomeTransition()) {
mPipBoundsState.setBounds(destinationBounds); return;
mSwipePipToHomeOverlay = overlay; }
mPipBoundsState.setBounds(destinationBounds);
mSwipePipToHomeOverlay = overlay;
if (ENABLE_SHELL_TRANSITIONS) {
// With Shell transition, the overlay was attached to the remote transition leash, which
// will be removed when the current transition is finished, so we need to reparent it
// to the actual Task surface now.
// PipTransition is responsible to fade it out and cleanup when finishing the enter PIP
// transition.
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
mTaskOrganizer.reparentChildSurfaceToTask(taskId, overlay, t);
t.setLayer(overlay, Integer.MAX_VALUE);
t.apply();
} }
} }
@@ -682,7 +695,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private void onEndOfSwipePipToHomeTransition() { private void onEndOfSwipePipToHomeTransition() {
if (Transitions.ENABLE_SHELL_TRANSITIONS) { if (Transitions.ENABLE_SHELL_TRANSITIONS) {
mSwipePipToHomeOverlay = null;
return; return;
} }
@@ -836,6 +848,24 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
return false; return false;
} }
@Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (mTaskInfo == null || mLeash == null || mTaskInfo.taskId != taskId) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
}
return mLeash;
}
@Override @Override
public void onFixedRotationStarted(int displayId, int newRotation) { public void onFixedRotationStarted(int displayId, int newRotation) {
mNextRotation = newRotation; mNextRotation = newRotation;
@@ -891,9 +921,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
clearWaitForFixedRotation(); clearWaitForFixedRotation();
} }
/** Called when exiting PIP tranisiton is finished to do the state cleanup. */ /** Called when exiting PIP transition is finished to do the state cleanup. */
void onExitPipFinished(TaskInfo info) { void onExitPipFinished(TaskInfo info) {
clearWaitForFixedRotation(); clearWaitForFixedRotation();
if (mSwipePipToHomeOverlay != null) {
removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */);
mSwipePipToHomeOverlay = null;
}
mPipTransitionState.setInSwipePipToHomeTransition(false); mPipTransitionState.setInSwipePipToHomeTransition(false);
mPictureInPictureParams = null; mPictureInPictureParams = null;
mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED); mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED);

View File

@@ -604,11 +604,18 @@ public class PipTransition extends PipTransitionController {
&& taskInfo.pictureInPictureParams.isAutoEnterEnabled() && taskInfo.pictureInPictureParams.isAutoEnterEnabled()
&& mPipTransitionState.getInSwipePipToHomeTransition()) { && mPipTransitionState.getInSwipePipToHomeTransition()) {
mOneShotAnimationType = ANIM_TYPE_BOUNDS; mOneShotAnimationType = ANIM_TYPE_BOUNDS;
SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
tx.setMatrix(leash, Matrix.IDENTITY_MATRIX, new float[9]) startTransaction.setMatrix(leash, Matrix.IDENTITY_MATRIX, new float[9])
.setPosition(leash, destinationBounds.left, destinationBounds.top) .setPosition(leash, destinationBounds.left, destinationBounds.top)
.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height()); .setWindowCrop(leash, destinationBounds.width(), destinationBounds.height());
startTransaction.merge(tx); if (swipePipToHomeOverlay != null) {
// Launcher fade in the overlay on top of the fullscreen Task. It is possible we
// reparent the PIP activity to a new PIP task (in case there are other activities
// in the original Task), so we should also reparent the overlay to the PIP task.
startTransaction.reparent(swipePipToHomeOverlay, leash)
.setLayer(swipePipToHomeOverlay, Integer.MAX_VALUE);
mPipOrganizer.mSwipePipToHomeOverlay = null;
}
startTransaction.apply(); startTransaction.apply();
if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) { if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
// For fixed rotation, set the destination bounds to the new rotation coordinates // For fixed rotation, set the destination bounds to the new rotation coordinates
@@ -618,6 +625,10 @@ public class PipTransition extends PipTransitionController {
mPipBoundsState.setBounds(destinationBounds); mPipBoundsState.setBounds(destinationBounds);
onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, null /* tx */); onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, null /* tx */);
sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
if (swipePipToHomeOverlay != null) {
mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay,
null /* callback */, false /* withStartDelay */);
}
mPipTransitionState.setInSwipePipToHomeTransition(false); mPipTransitionState.setInSwipePipToHomeTransition(false);
return true; return true;
} }

View File

@@ -595,9 +595,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
return entryBounds; return entryBounds;
} }
private void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, private void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds,
SurfaceControl overlay) { SurfaceControl overlay) {
mPipTaskOrganizer.stopSwipePipToHome(componentName, destinationBounds, overlay); mPipTaskOrganizer.stopSwipePipToHome(taskId, componentName, destinationBounds, overlay);
} }
private String getTransitionTag(int direction) { private String getTransitionTag(int direction) {
@@ -928,11 +928,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb
} }
@Override @Override
public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, public void stopSwipePipToHome(int taskId, ComponentName componentName,
SurfaceControl overlay) { Rect destinationBounds, SurfaceControl overlay) {
executeRemoteCallWithTaskPermission(mController, "stopSwipePipToHome", executeRemoteCallWithTaskPermission(mController, "stopSwipePipToHome",
(controller) -> { (controller) -> {
controller.stopSwipePipToHome(componentName, destinationBounds, overlay); controller.stopSwipePipToHome(taskId, componentName, destinationBounds,
overlay);
}); });
} }

View File

@@ -280,10 +280,20 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
@Override @Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) { public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (mRootTaskInfo.taskId == taskId) { if (mRootTaskInfo.taskId == taskId) {
b.setParent(mRootLeash); return mRootLeash;
} else if (mChildrenLeashes.contains(taskId)) { } else if (mChildrenLeashes.contains(taskId)) {
b.setParent(mChildrenLeashes.get(taskId)); return mChildrenLeashes.get(taskId);
} else { } else {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId); throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
} }

View File

@@ -227,10 +227,20 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
@Override @Override
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) { public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
b.setParent(findTaskSurface(taskId));
}
@Override
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
SurfaceControl.Transaction t) {
t.reparent(sc, findTaskSurface(taskId));
}
private SurfaceControl findTaskSurface(int taskId) {
if (mRootTaskInfo.taskId == taskId) { if (mRootTaskInfo.taskId == taskId) {
b.setParent(mRootLeash); return mRootLeash;
} else if (mChildrenLeashes.contains(taskId)) { } else if (mChildrenLeashes.contains(taskId)) {
b.setParent(mChildrenLeashes.get(taskId)); return mChildrenLeashes.get(taskId);
} else { } else {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId); throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
} }