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 efff3e30f010d..6c3576b438b13 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 @@ -614,6 +614,12 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } private void onEndOfSwipePipToHomeTransition() { + if (Transitions.ENABLE_SHELL_TRANSITIONS) { + mInSwipePipToHomeTransition = false; + mSwipePipToHomeOverlay = null; + return; + } + final Rect destinationBounds = mPipBoundsState.getBounds(); final SurfaceControl swipeToHomeOverlay = mSwipePipToHomeOverlay; final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); 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 b75cde099bcbb..18153e3f4246a 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 @@ -32,6 +32,7 @@ import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP; import android.app.TaskInfo; import android.content.Context; +import android.graphics.Matrix; import android.graphics.Rect; import android.os.IBinder; import android.view.Surface; @@ -214,6 +215,25 @@ public class PipTransition extends PipTransitionController { final Rect currentBounds = taskInfo.configuration.windowConfiguration.getBounds(); PipAnimationController.PipTransitionAnimator animator; finishTransaction.setPosition(leash, destinationBounds.left, destinationBounds.top); + if (taskInfo.pictureInPictureParams != null + && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) { + mOneShotAnimationType = ANIM_TYPE_BOUNDS; + + // PiP menu is attached late in the process here to avoid any artifacts on the leash + // caused by addShellRoot when in gesture navigation mode. + mPipMenuController.attach(leash); + SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); + tx.setMatrix(leash, Matrix.IDENTITY_MATRIX, new float[9]) + .setPosition(leash, destinationBounds.left, destinationBounds.top) + .setWindowCrop(leash, destinationBounds.width(), destinationBounds.height()); + startTransaction.merge(tx); + startTransaction.apply(); + mPipBoundsState.setBounds(destinationBounds); + onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, tx); + sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); + mFinishCallback = null; + return true; + } if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java index a77cc87a4e2ca..3eea99a462455 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java @@ -27,6 +27,7 @@ import static android.window.TransitionFilter.CONTAINER_ORDER_TOP; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; +import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.graphics.Rect; import android.os.IBinder; @@ -122,15 +123,20 @@ public class RemoteTransitionCompat implements Parcelable { // This transition is for opening recents, so recents is on-top. We want to draw // the current going-away task on top of recents, though, so move it to front WindowContainerToken pausingTask = null; - SurfaceControl pausingLeash = null; + WindowContainerToken pipTask = null; for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) { t.setLayer(leashMap.get(change.getLeash()), info.getChanges().size() * 3 - i); - if (change.getTaskInfo() != null) { + final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); + if (taskInfo != null) { pausingTask = change.getTaskInfo().token; } + if (taskInfo.pictureInPictureParams != null + && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) { + pipTask = change.getTaskInfo().token; + } } } // Also make all the wallpapers opaque since we want the visible from the start @@ -138,7 +144,7 @@ public class RemoteTransitionCompat implements Parcelable { t.setAlpha(wallpapers[i].leash.mSurfaceControl, 1); } t.apply(); - mRecentsSession.setup(controller, info, finishedCallback, pausingTask, + mRecentsSession.setup(controller, info, finishedCallback, pausingTask, pipTask, leashMap, mToken); recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0), new Rect()); @@ -183,14 +189,17 @@ public class RemoteTransitionCompat implements Parcelable { private RecentsAnimationControllerCompat mWrapped = null; private IRemoteTransitionFinishedCallback mFinishCB = null; private WindowContainerToken mPausingTask = null; + private WindowContainerToken mPipTask = null; private TransitionInfo mInfo = null; private SurfaceControl mOpeningLeash = null; private ArrayMap mLeashMap = null; + private PictureInPictureSurfaceTransaction mPipTransaction = null; private IBinder mTransition = null; void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info, IRemoteTransitionFinishedCallback finishCB, WindowContainerToken pausingTask, - ArrayMap leashMap, IBinder transition) { + WindowContainerToken pipTask, ArrayMap leashMap, + IBinder transition) { if (mInfo != null) { throw new IllegalStateException("Trying to run a new recents animation while" + " recents is already active."); @@ -199,6 +208,7 @@ public class RemoteTransitionCompat implements Parcelable { mInfo = info; mFinishCB = finishCB; mPausingTask = pausingTask; + mPipTask = pipTask; mLeashMap = leashMap; mTransition = transition; } @@ -257,6 +267,7 @@ public class RemoteTransitionCompat implements Parcelable { @Override public void setFinishTaskTransaction(int taskId, PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) { + mPipTransaction = finishTransaction; if (mWrapped != null) { mWrapped.setFinishTaskTransaction(taskId, finishTransaction, overlay); } @@ -288,7 +299,18 @@ public class RemoteTransitionCompat implements Parcelable { t.setAlpha(mOpeningLeash, 1.f); t.apply(); } - mFinishCB.onTransitionFinished(null /* wct */, null /* sct */); + if (mPipTask != null && mPipTransaction != null) { + final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + t.show(mInfo.getChange(mPipTask).getLeash()); + PictureInPictureSurfaceTransaction.apply(mPipTransaction, + mInfo.getChange(mPipTask).getLeash(), t); + mPipTask = null; + mPipTransaction = null; + mFinishCB.onTransitionFinished(null /* wct */, t); + } else { + mFinishCB.onTransitionFinished(null /* wct */, null /* sct */); + } + } } catch (RemoteException e) { Log.e("RemoteTransitionCompat", "Failed to call animation finish callback", e); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 62e52cb293e2e..45eb7cdcbf6cb 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -5274,7 +5274,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // returns. Just need to confirm this reasoning makes sense. final boolean deferHidingClient = canEnterPictureInPicture && !isState(STARTED, STOPPING, STOPPED, PAUSED); - if (deferHidingClient && pictureInPictureArgs.isAutoEnterEnabled()) { + if (!mAtmService.getTransitionController().isShellTransitionsEnabled() + && deferHidingClient && pictureInPictureArgs.isAutoEnterEnabled()) { // Go ahead and just put the activity in pip if it supports auto-pip. mAtmService.enterPictureInPictureMode(this, pictureInPictureArgs); return; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index c803f06840d09..d8681f6a0c9d9 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3365,9 +3365,9 @@ class Task extends TaskFragment { private @Nullable PictureInPictureParams getPictureInPictureParams(Task top) { if (top == null) return null; - final ActivityRecord topVisibleActivity = top.getTopVisibleActivity(); - return (topVisibleActivity == null || topVisibleActivity.pictureInPictureArgs.empty()) - ? null : new PictureInPictureParams(topVisibleActivity.pictureInPictureArgs); + final ActivityRecord topMostActivity = top.getTopMostActivity(); + return (topMostActivity == null || topMostActivity.pictureInPictureArgs.empty()) + ? null : new PictureInPictureParams(topMostActivity.pictureInPictureArgs); } /** diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 0a8a9373e141c..90e607337b7ab 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -305,17 +305,27 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord(); if (ar != null) { if (!ar.isVisibleRequested()) { - // If activity is capable of entering PiP, give it a chance to enter it now. + boolean commitVisibility = true; if (ar.getDeferHidingClient() && ar.getTask() != null) { - mController.mAtm.mTaskSupervisor.mUserLeaving = true; - ar.getTaskFragment().startPausing(false /* uiSleeping */, - null /* resuming */, "finishTransition"); - mController.mAtm.mTaskSupervisor.mUserLeaving = false; + if (ar.pictureInPictureArgs != null + && ar.pictureInPictureArgs.isAutoEnterEnabled()) { + mController.mAtm.enterPictureInPictureMode(ar, ar.pictureInPictureArgs); + // Avoid commit visibility to false here, or else we will get a sudden + // "flash" / surface going invisible for a split second. + commitVisibility = false; + } else { + mController.mAtm.mTaskSupervisor.mUserLeaving = true; + ar.getTaskFragment().startPausing(false /* uiSleeping */, + null /* resuming */, "finishTransition"); + mController.mAtm.mTaskSupervisor.mUserLeaving = false; + } + } + if (commitVisibility) { + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, + " Commit activity becoming invisible: %s", ar); + ar.commitVisibility(false /* visible */, false /* performLayout */); + activitiesWentInvisible = true; } - ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, - " Commit activity becoming invisible: %s", ar); - ar.commitVisibility(false /* visible */, false /* performLayout */); - activitiesWentInvisible = true; } if (mChanges.get(ar).mVisible != ar.isVisibleRequested()) { // Legacy dispatch relies on this (for now).