Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +4 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ import java.util.Objects; */ public class PipAnimationController { static final float FRACTION_START = 0f; private static final float FRACTION_END = 1f; static final float FRACTION_END = 1f; public static final int ANIM_TYPE_BOUNDS = 0; public static final int ANIM_TYPE_ALPHA = 1; Loading Loading @@ -718,8 +718,10 @@ public class PipAnimationController { .round(tx, leash, sourceBounds, bounds) .shadow(tx, leash, shouldApplyShadowRadius()); } if (!handlePipTransaction(leash, tx, bounds, 1f /* alpha */)) { tx.apply(); } } private Rect computeInsets(float fraction) { if (sourceHintRectInsets == null) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +1 −0 Original line number Diff line number Diff line Loading @@ -828,6 +828,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private void onEndOfSwipePipToHomeTransition() { if (Transitions.ENABLE_SHELL_TRANSITIONS) { mPipTransitionController.setEnterAnimationType(ANIM_TYPE_BOUNDS); return; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +92 −48 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ import android.animation.Animator; import android.app.ActivityManager; import android.app.TaskInfo; import android.content.Context; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; Loading Loading @@ -109,6 +108,17 @@ public class PipTransition extends PipTransitionController { /** Whether the PIP window has fade out for fixed rotation. */ private boolean mHasFadeOut; /** Used for setting transform to a transaction from animator. */ private final PipAnimationController.PipTransactionHandler mTransactionConsumer = new PipAnimationController.PipTransactionHandler() { @Override public boolean handlePipTransaction(SurfaceControl leash, SurfaceControl.Transaction tx, Rect destinationBounds, float alpha) { // Only set the operation to transaction but do not apply. return true; } }; public PipTransition(Context context, @NonNull ShellInit shellInit, @NonNull ShellTaskOrganizer shellTaskOrganizer, Loading Loading @@ -338,7 +348,7 @@ public class PipTransition extends PipTransitionController { @Override public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds, @PipAnimationController.TransitionDirection int direction, @Nullable SurfaceControl.Transaction tx) { @NonNull SurfaceControl.Transaction tx) { final boolean enteringPip = isInPipDirection(direction); if (enteringPip) { mPipTransitionState.setTransitionState(ENTERED_PIP); Loading @@ -348,13 +358,15 @@ public class PipTransition extends PipTransitionController { // (likely a remote like launcher), so don't fire the finish-callback here -- wait until // the exit transition is merged. if ((mExitTransition == null || isAnimatingLocally()) && mFinishCallback != null) { final SurfaceControl leash = mPipOrganizer.getSurfaceControl(); final boolean hasValidLeash = leash != null && leash.isValid(); WindowContainerTransaction wct = null; if (isOutPipDirection(direction)) { // Only need to reset surface properties. The server-side operations were already // done at the start. But if it is running fixed rotation, there will be a seamless // display transition later. So the last rotation transform needs to be kept to // avoid flickering, and then the display transition will reset the transform. if (tx != null && !mInFixedRotation) { if (!mInFixedRotation && mFinishTransaction != null) { mFinishTransaction.merge(tx); } } else { Loading @@ -363,28 +375,37 @@ public class PipTransition extends PipTransitionController { // If we are animating from fullscreen using a bounds animation, then reset the // activity windowing mode, and set the task bounds to the final bounds wct.setActivityWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED); wct.scheduleFinishEnterPip(taskInfo.token, destinationBounds); wct.setBounds(taskInfo.token, destinationBounds); } else { wct.setBounds(taskInfo.token, null /* bounds */); } if (tx != null) { wct.setBoundsChangeTransaction(taskInfo.token, tx); // Reset the scale with bounds change synchronously. if (hasValidLeash) { mSurfaceTransactionHelper.crop(tx, leash, destinationBounds) .resetScale(tx, leash, destinationBounds) .round(tx, leash, true /* applyCornerRadius */); } wct.setBoundsChangeTransaction(taskInfo.token, tx); } final SurfaceControl leash = mPipOrganizer.getSurfaceControl(); final int displayRotation = taskInfo.getConfiguration().windowConfiguration .getDisplayRotation(); if (enteringPip && mInFixedRotation && mEndFixedRotation != displayRotation && leash != null && leash.isValid()) { && hasValidLeash) { // Launcher may update the Shelf height during the animation, which will update the // destination bounds. Because this is in fixed rotation, We need to make sure the // finishTransaction is using the updated bounds in the display rotation. final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController.getCurrentAnimator(); final Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds(); final Rect finishBounds = new Rect(destinationBounds); rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation); if (!finishBounds.equals(animator.getEndValue())) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Destination bounds were changed during animation", TAG); rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation); mSurfaceTransactionHelper.crop(mFinishTransaction, leash, finishBounds); } } mFinishTransaction = null; callFinishCallback(wct); } Loading Loading @@ -665,9 +686,11 @@ public class PipTransition extends PipTransitionController { private void startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash, final Rect baseBounds, final Rect startBounds, final Rect endBounds, final int rotationDelta) { final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( taskInfo.pictureInPictureParams, endBounds); final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController.getAnimator(taskInfo, leash, baseBounds, startBounds, endBounds, null /* sourceHintRect */, TRANSITION_DIRECTION_LEAVE_PIP, endBounds, sourceHintRect, TRANSITION_DIRECTION_LEAVE_PIP, 0 /* startingAngle */, rotationDelta); animator.setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP) .setPipAnimationCallback(mPipAnimationCallback) Loading Loading @@ -800,10 +823,6 @@ public class PipTransition extends PipTransitionController { computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo, destinationBounds, sourceHintRect); } // Set corner radius for entering pip. mSurfaceTransactionHelper .crop(finishTransaction, leash, destinationBounds) .round(finishTransaction, leash, true /* applyCornerRadius */); if (!mPipOrganizer.shouldAttachMenuEarly()) { mTransitions.getMainExecutor().executeDelayed( () -> mPipMenuController.attach(leash), 0); Loading @@ -812,41 +831,11 @@ public class PipTransition extends PipTransitionController { if (taskInfo.pictureInPictureParams != null && taskInfo.pictureInPictureParams.isAutoEnterEnabled() && mPipTransitionState.getInSwipePipToHomeTransition()) { 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()); 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 // at the end. destinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds()); } 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); handleSwipePipToHomeTransition(startTransaction, finishTransaction, leash, sourceHintRect, destinationBounds, rotationDelta, taskInfo); return; } if (rotationDelta != Surface.ROTATION_0) { Matrix tmpTransform = new Matrix(); tmpTransform.postRotate(rotationDelta); startTransaction.setMatrix(leash, tmpTransform, new float[9]); } final int enterAnimationType = mEnterAnimationType; if (enterAnimationType == ANIM_TYPE_ALPHA) { startTransaction.setAlpha(leash, 0f); Loading Loading @@ -880,11 +869,13 @@ public class PipTransition extends PipTransitionController { } else if (enterAnimationType == ANIM_TYPE_ALPHA) { animator = mPipAnimationController.getAnimator(taskInfo, leash, destinationBounds, 0f, 1f); mSurfaceTransactionHelper .crop(finishTransaction, leash, destinationBounds) .round(finishTransaction, leash, true /* applyCornerRadius */); } else { throw new RuntimeException("Unrecognized animation type: " + enterAnimationType); } animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP) .setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler()) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(mEnterExitAnimationDuration); if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) { Loading @@ -893,7 +884,15 @@ public class PipTransition extends PipTransitionController { // ComputeRotatedBounds has changed the DisplayLayout without affecting the animation. animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds()); } animator.start(); // Keep the last appearance when finishing the transition. The transform will be reset when // setting bounds. animator.setPipTransactionHandler(mTransactionConsumer).applySurfaceControlTransaction( leash, finishTransaction, PipAnimationController.FRACTION_END); // Remove the workaround after fixing ClosePipBySwipingDownTest that detects the shadow // as unexpected visible. finishTransaction.setShadowRadius(leash, 0); // Start to animate enter PiP. animator.setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler()).start(); } /** Computes destination bounds in old rotation and updates source hint rect if available. */ Loading @@ -915,6 +914,51 @@ public class PipTransition extends PipTransitionController { } } private void handleSwipePipToHomeTransition( @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull SurfaceControl leash, @Nullable Rect sourceHintRect, @NonNull Rect destinationBounds, int rotationDelta, @NonNull ActivityManager.RunningTaskInfo pipTaskInfo) { final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay; 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; } Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds(); if (!Transitions.SHELL_TRANSITIONS_ROTATION && rotationDelta % 2 == 1) { // PipController#startSwipePipToHome has updated the display layout to new rotation, // so flip the source bounds to match the same orientation. sourceBounds = new Rect(0, 0, sourceBounds.height(), sourceBounds.width()); } final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController.getAnimator(pipTaskInfo, leash, sourceBounds, sourceBounds, destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP, 0 /* startingAngle */, 0 /* rotationDelta */) .setPipTransactionHandler(mTransactionConsumer) .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP); // The start state is the end state for swipe-auto-pip. startTransaction.merge(finishTransaction); animator.applySurfaceControlTransaction(leash, startTransaction, PipAnimationController.FRACTION_END); startTransaction.apply(); mPipBoundsState.setBounds(destinationBounds); final SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); onFinishResize(pipTaskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, tx); sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); if (swipePipToHomeOverlay != null) { mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay, null /* callback */, false /* withStartDelay */); } mPipTransitionState.setInSwipePipToHomeTransition(false); } private void startExitToSplitAnimation(@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +4 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ import java.util.Objects; */ public class PipAnimationController { static final float FRACTION_START = 0f; private static final float FRACTION_END = 1f; static final float FRACTION_END = 1f; public static final int ANIM_TYPE_BOUNDS = 0; public static final int ANIM_TYPE_ALPHA = 1; Loading Loading @@ -718,8 +718,10 @@ public class PipAnimationController { .round(tx, leash, sourceBounds, bounds) .shadow(tx, leash, shouldApplyShadowRadius()); } if (!handlePipTransaction(leash, tx, bounds, 1f /* alpha */)) { tx.apply(); } } private Rect computeInsets(float fraction) { if (sourceHintRectInsets == null) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +1 −0 Original line number Diff line number Diff line Loading @@ -828,6 +828,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private void onEndOfSwipePipToHomeTransition() { if (Transitions.ENABLE_SHELL_TRANSITIONS) { mPipTransitionController.setEnterAnimationType(ANIM_TYPE_BOUNDS); return; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +92 −48 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ import android.animation.Animator; import android.app.ActivityManager; import android.app.TaskInfo; import android.content.Context; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; Loading Loading @@ -109,6 +108,17 @@ public class PipTransition extends PipTransitionController { /** Whether the PIP window has fade out for fixed rotation. */ private boolean mHasFadeOut; /** Used for setting transform to a transaction from animator. */ private final PipAnimationController.PipTransactionHandler mTransactionConsumer = new PipAnimationController.PipTransactionHandler() { @Override public boolean handlePipTransaction(SurfaceControl leash, SurfaceControl.Transaction tx, Rect destinationBounds, float alpha) { // Only set the operation to transaction but do not apply. return true; } }; public PipTransition(Context context, @NonNull ShellInit shellInit, @NonNull ShellTaskOrganizer shellTaskOrganizer, Loading Loading @@ -338,7 +348,7 @@ public class PipTransition extends PipTransitionController { @Override public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds, @PipAnimationController.TransitionDirection int direction, @Nullable SurfaceControl.Transaction tx) { @NonNull SurfaceControl.Transaction tx) { final boolean enteringPip = isInPipDirection(direction); if (enteringPip) { mPipTransitionState.setTransitionState(ENTERED_PIP); Loading @@ -348,13 +358,15 @@ public class PipTransition extends PipTransitionController { // (likely a remote like launcher), so don't fire the finish-callback here -- wait until // the exit transition is merged. if ((mExitTransition == null || isAnimatingLocally()) && mFinishCallback != null) { final SurfaceControl leash = mPipOrganizer.getSurfaceControl(); final boolean hasValidLeash = leash != null && leash.isValid(); WindowContainerTransaction wct = null; if (isOutPipDirection(direction)) { // Only need to reset surface properties. The server-side operations were already // done at the start. But if it is running fixed rotation, there will be a seamless // display transition later. So the last rotation transform needs to be kept to // avoid flickering, and then the display transition will reset the transform. if (tx != null && !mInFixedRotation) { if (!mInFixedRotation && mFinishTransaction != null) { mFinishTransaction.merge(tx); } } else { Loading @@ -363,28 +375,37 @@ public class PipTransition extends PipTransitionController { // If we are animating from fullscreen using a bounds animation, then reset the // activity windowing mode, and set the task bounds to the final bounds wct.setActivityWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED); wct.scheduleFinishEnterPip(taskInfo.token, destinationBounds); wct.setBounds(taskInfo.token, destinationBounds); } else { wct.setBounds(taskInfo.token, null /* bounds */); } if (tx != null) { wct.setBoundsChangeTransaction(taskInfo.token, tx); // Reset the scale with bounds change synchronously. if (hasValidLeash) { mSurfaceTransactionHelper.crop(tx, leash, destinationBounds) .resetScale(tx, leash, destinationBounds) .round(tx, leash, true /* applyCornerRadius */); } wct.setBoundsChangeTransaction(taskInfo.token, tx); } final SurfaceControl leash = mPipOrganizer.getSurfaceControl(); final int displayRotation = taskInfo.getConfiguration().windowConfiguration .getDisplayRotation(); if (enteringPip && mInFixedRotation && mEndFixedRotation != displayRotation && leash != null && leash.isValid()) { && hasValidLeash) { // Launcher may update the Shelf height during the animation, which will update the // destination bounds. Because this is in fixed rotation, We need to make sure the // finishTransaction is using the updated bounds in the display rotation. final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController.getCurrentAnimator(); final Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds(); final Rect finishBounds = new Rect(destinationBounds); rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation); if (!finishBounds.equals(animator.getEndValue())) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Destination bounds were changed during animation", TAG); rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation); mSurfaceTransactionHelper.crop(mFinishTransaction, leash, finishBounds); } } mFinishTransaction = null; callFinishCallback(wct); } Loading Loading @@ -665,9 +686,11 @@ public class PipTransition extends PipTransitionController { private void startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash, final Rect baseBounds, final Rect startBounds, final Rect endBounds, final int rotationDelta) { final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( taskInfo.pictureInPictureParams, endBounds); final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController.getAnimator(taskInfo, leash, baseBounds, startBounds, endBounds, null /* sourceHintRect */, TRANSITION_DIRECTION_LEAVE_PIP, endBounds, sourceHintRect, TRANSITION_DIRECTION_LEAVE_PIP, 0 /* startingAngle */, rotationDelta); animator.setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP) .setPipAnimationCallback(mPipAnimationCallback) Loading Loading @@ -800,10 +823,6 @@ public class PipTransition extends PipTransitionController { computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo, destinationBounds, sourceHintRect); } // Set corner radius for entering pip. mSurfaceTransactionHelper .crop(finishTransaction, leash, destinationBounds) .round(finishTransaction, leash, true /* applyCornerRadius */); if (!mPipOrganizer.shouldAttachMenuEarly()) { mTransitions.getMainExecutor().executeDelayed( () -> mPipMenuController.attach(leash), 0); Loading @@ -812,41 +831,11 @@ public class PipTransition extends PipTransitionController { if (taskInfo.pictureInPictureParams != null && taskInfo.pictureInPictureParams.isAutoEnterEnabled() && mPipTransitionState.getInSwipePipToHomeTransition()) { 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()); 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 // at the end. destinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds()); } 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); handleSwipePipToHomeTransition(startTransaction, finishTransaction, leash, sourceHintRect, destinationBounds, rotationDelta, taskInfo); return; } if (rotationDelta != Surface.ROTATION_0) { Matrix tmpTransform = new Matrix(); tmpTransform.postRotate(rotationDelta); startTransaction.setMatrix(leash, tmpTransform, new float[9]); } final int enterAnimationType = mEnterAnimationType; if (enterAnimationType == ANIM_TYPE_ALPHA) { startTransaction.setAlpha(leash, 0f); Loading Loading @@ -880,11 +869,13 @@ public class PipTransition extends PipTransitionController { } else if (enterAnimationType == ANIM_TYPE_ALPHA) { animator = mPipAnimationController.getAnimator(taskInfo, leash, destinationBounds, 0f, 1f); mSurfaceTransactionHelper .crop(finishTransaction, leash, destinationBounds) .round(finishTransaction, leash, true /* applyCornerRadius */); } else { throw new RuntimeException("Unrecognized animation type: " + enterAnimationType); } animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP) .setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler()) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(mEnterExitAnimationDuration); if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) { Loading @@ -893,7 +884,15 @@ public class PipTransition extends PipTransitionController { // ComputeRotatedBounds has changed the DisplayLayout without affecting the animation. animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds()); } animator.start(); // Keep the last appearance when finishing the transition. The transform will be reset when // setting bounds. animator.setPipTransactionHandler(mTransactionConsumer).applySurfaceControlTransaction( leash, finishTransaction, PipAnimationController.FRACTION_END); // Remove the workaround after fixing ClosePipBySwipingDownTest that detects the shadow // as unexpected visible. finishTransaction.setShadowRadius(leash, 0); // Start to animate enter PiP. animator.setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler()).start(); } /** Computes destination bounds in old rotation and updates source hint rect if available. */ Loading @@ -915,6 +914,51 @@ public class PipTransition extends PipTransitionController { } } private void handleSwipePipToHomeTransition( @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull SurfaceControl leash, @Nullable Rect sourceHintRect, @NonNull Rect destinationBounds, int rotationDelta, @NonNull ActivityManager.RunningTaskInfo pipTaskInfo) { final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay; 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; } Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds(); if (!Transitions.SHELL_TRANSITIONS_ROTATION && rotationDelta % 2 == 1) { // PipController#startSwipePipToHome has updated the display layout to new rotation, // so flip the source bounds to match the same orientation. sourceBounds = new Rect(0, 0, sourceBounds.height(), sourceBounds.width()); } final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController.getAnimator(pipTaskInfo, leash, sourceBounds, sourceBounds, destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP, 0 /* startingAngle */, 0 /* rotationDelta */) .setPipTransactionHandler(mTransactionConsumer) .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP); // The start state is the end state for swipe-auto-pip. startTransaction.merge(finishTransaction); animator.applySurfaceControlTransaction(leash, startTransaction, PipAnimationController.FRACTION_END); startTransaction.apply(); mPipBoundsState.setBounds(destinationBounds); final SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); onFinishResize(pipTaskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, tx); sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP); if (swipePipToHomeOverlay != null) { mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay, null /* callback */, false /* withStartDelay */); } mPipTransitionState.setInSwipePipToHomeTransition(false); } private void startExitToSplitAnimation(@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, Loading