diff options
12 files changed, 178 insertions, 30 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 91ea436f81b6..3f8343a7abd3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -98,16 +98,22 @@ public class ShellTaskOrganizer extends TaskOrganizer implements default void onTaskInfoChanged(RunningTaskInfo taskInfo) {} default void onTaskVanished(RunningTaskInfo taskInfo) {} default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {} - /** Whether this task listener supports compat UI. */ + /** Whether this task listener supports compat UI. */ default boolean supportCompatUI() { // All TaskListeners should support compat UI except PIP. 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) { throw new IllegalStateException( "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) {}; } @@ -620,6 +626,23 @@ public class ShellTaskOrganizer extends TaskOrganizer implements 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, int event) { ActivityInfo topActivityInfo = info.getTaskInfo().topActivityInfo; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java index 54e743f72cc6..ca4ef07eb1db 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java @@ -367,10 +367,20 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback, @Override 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); } - b.setParent(mTaskLeash); + return mTaskLeash; } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java index e344c3bea42b..33eec335bca3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java @@ -275,12 +275,22 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou @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 (getRootTaskId() == taskId) { - b.setParent(mRootTaskLeash); + return mRootTaskLeash; } else if (getTaskId1() == taskId) { - b.setParent(mTaskLeash1); + return mTaskLeash1; } else if (getTaskId2() == taskId) { - b.setParent(mTaskLeash2); + return mTaskLeash2; } else { throw new IllegalArgumentException("There is no surface for taskId=" + taskId); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java index 52ff21bc3172..fef9be36a35f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java @@ -110,6 +110,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 public void dump(PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; pw.println(prefix + this); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java index 6e38e421d4b6..73e6cba43ec0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java @@ -133,10 +133,20 @@ public class FullscreenTaskListener 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 (!mDataByTaskId.contains(taskId)) { throw new IllegalArgumentException("There is no surface for taskId=" + taskId); } - b.setParent(mDataByTaskId.get(taskId).surface); + return mDataByTaskId.get(taskId).surface; } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java index 86bf3ff1cea9..d2f42c39acd5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java @@ -343,10 +343,20 @@ class LegacySplitScreenTaskListener 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 (!mLeashByTaskId.contains(taskId)) { throw new IllegalArgumentException("There is no surface for taskId=" + taskId); } - b.setParent(mLeashByTaskId.get(taskId)); + return mLeashByTaskId.get(taskId); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl index ddc85f758916..e03421dd58ac 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl @@ -47,12 +47,13 @@ interface IPip { /** * 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 destinationBounds the destination bounds the PiP window lands into * @param overlay an optional overlay to fade out after entering PiP */ - oneway void stopSwipePipToHome(in ComponentName componentName, in Rect destinationBounds, - in SurfaceControl overlay) = 2; + oneway void stopSwipePipToHome(int taskId, in ComponentName componentName, + in Rect destinationBounds, in SurfaceControl overlay) = 2; /** * Sets listener to get pinned stack animation callbacks. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index f9ec88659eea..bfa14f3a705d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -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 * {@link PipTransitionState#getInSwipePipToHomeTransition()} is true. */ - private SurfaceControl mSwipePipToHomeOverlay; + @Nullable + SurfaceControl mSwipePipToHomeOverlay; public PipTaskOrganizer(Context context, @NonNull SyncTransactionQueue syncTransactionQueue, @@ -357,12 +358,24 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, * Callback when launcher finishes swipe-pip-to-home operation. * 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) { // do nothing if there is no startSwipePipToHome being called before - if (mPipTransitionState.getInSwipePipToHomeTransition()) { - mPipBoundsState.setBounds(destinationBounds); - mSwipePipToHomeOverlay = overlay; + if (!mPipTransitionState.getInSwipePipToHomeTransition()) { + return; + } + 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() { if (Transitions.ENABLE_SHELL_TRANSITIONS) { - mSwipePipToHomeOverlay = null; return; } @@ -837,6 +849,24 @@ public class PipTaskOrganizer 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 (mTaskInfo == null || mLeash == null || mTaskInfo.taskId != taskId) { + throw new IllegalArgumentException("There is no surface for taskId=" + taskId); + } + return mLeash; + } + + @Override public void onFixedRotationStarted(int displayId, int newRotation) { mNextRotation = newRotation; mWaitForFixedRotation = true; @@ -891,9 +921,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, 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) { clearWaitForFixedRotation(); + if (mSwipePipToHomeOverlay != null) { + removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */); + mSwipePipToHomeOverlay = null; + } mPipTransitionState.setInSwipePipToHomeTransition(false); mPictureInPictureParams = null; mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index 4cab6d336892..401dc9ae02e1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -604,11 +604,18 @@ public class PipTransition extends PipTransitionController { && taskInfo.pictureInPictureParams.isAutoEnterEnabled() && mPipTransitionState.getInSwipePipToHomeTransition()) { mOneShotAnimationType = ANIM_TYPE_BOUNDS; - SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); - tx.setMatrix(leash, Matrix.IDENTITY_MATRIX, new float[9]) + final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay; + startTransaction.setMatrix(leash, Matrix.IDENTITY_MATRIX, new float[9]) .setPosition(leash, destinationBounds.left, destinationBounds.top) .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(); if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) { // For fixed rotation, set the destination bounds to the new rotation coordinates @@ -618,6 +625,10 @@ public class PipTransition extends PipTransitionController { mPipBoundsState.setBounds(destinationBounds); onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, null /* tx */); sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + if (swipePipToHomeOverlay != null) { + mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay, + null /* callback */, false /* withStartDelay */); + } mPipTransitionState.setInSwipePipToHomeTransition(false); return true; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 5b6c95eef561..e7a1c4cca07e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -595,9 +595,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb return entryBounds; } - private void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, + private void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds, SurfaceControl overlay) { - mPipTaskOrganizer.stopSwipePipToHome(componentName, destinationBounds, overlay); + mPipTaskOrganizer.stopSwipePipToHome(taskId, componentName, destinationBounds, overlay); } private String getTransitionTag(int direction) { @@ -928,11 +928,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb } @Override - public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, - SurfaceControl overlay) { + public void stopSwipePipToHome(int taskId, ComponentName componentName, + Rect destinationBounds, SurfaceControl overlay) { executeRemoteCallWithTaskPermission(mController, "stopSwipePipToHome", (controller) -> { - controller.stopSwipePipToHome(componentName, destinationBounds, overlay); + controller.stopSwipePipToHome(taskId, componentName, destinationBounds, + overlay); }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index c5aab45f56fa..109f96e166d7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -280,10 +280,20 @@ class StageTaskListener 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 (mRootTaskInfo.taskId == taskId) { - b.setParent(mRootLeash); + return mRootLeash; } else if (mChildrenLeashes.contains(taskId)) { - b.setParent(mChildrenLeashes.get(taskId)); + return mChildrenLeashes.get(taskId); } else { throw new IllegalArgumentException("There is no surface for taskId=" + taskId); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageTaskListener.java index 8b36c9406b15..7b679580fa87 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageTaskListener.java @@ -227,10 +227,20 @@ class StageTaskListener 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 (mRootTaskInfo.taskId == taskId) { - b.setParent(mRootLeash); + return mRootLeash; } else if (mChildrenLeashes.contains(taskId)) { - b.setParent(mChildrenLeashes.get(taskId)); + return mChildrenLeashes.get(taskId); } else { throw new IllegalArgumentException("There is no surface for taskId=" + taskId); } |