diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index 200af7415eb15..05111a3d44369 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -38,6 +38,7 @@ import android.view.SurfaceSession; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.wm.shell.animation.Interpolators; +import com.android.wm.shell.transition.Transitions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -617,14 +618,28 @@ public class PipAnimationController { setCurrentValue(bounds); final Rect insets = computeInsets(fraction); final float degree, x, y; - if (rotationDelta == ROTATION_90) { - degree = 90 * fraction; - x = fraction * (end.right - start.left) + start.left; - y = fraction * (end.top - start.top) + start.top; + if (Transitions.ENABLE_SHELL_TRANSITIONS) { + if (rotationDelta == ROTATION_90) { + degree = 90 * (1 - fraction); + x = fraction * (end.left - start.left) + + start.left + start.right * (1 - fraction); + y = fraction * (end.top - start.top) + start.top; + } else { + degree = -90 * (1 - fraction); + x = fraction * (end.left - start.left) + start.left; + y = fraction * (end.top - start.top) + + start.top + start.bottom * (1 - fraction); + } } else { - degree = -90 * fraction; - x = fraction * (end.left - start.left) + start.left; - y = fraction * (end.bottom - start.top) + start.top; + if (rotationDelta == ROTATION_90) { + degree = 90 * fraction; + x = fraction * (end.right - start.left) + start.left; + y = fraction * (end.top - start.top) + start.top; + } else { + degree = -90 * fraction; + x = fraction * (end.left - start.left) + start.left; + y = fraction * (end.bottom - start.top) + start.top; + } } getSurfaceTransactionHelper() .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java index 728794de0865b..180e3fb48c9d9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java @@ -23,6 +23,7 @@ import android.graphics.RectF; import android.view.SurfaceControl; import com.android.wm.shell.R; +import com.android.wm.shell.transition.Transitions; /** * Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition. @@ -137,7 +138,8 @@ public class PipSurfaceTransactionHelper { // destination are different. final float scale = srcW <= srcH ? (float) destW / srcW : (float) destH / srcH; final Rect crop = mTmpDestinationRect; - crop.set(0, 0, destW, destH); + crop.set(0, 0, Transitions.ENABLE_SHELL_TRANSITIONS ? destH + : destW, Transitions.ENABLE_SHELL_TRANSITIONS ? destW : destH); // Inverse scale for crop to fit in screen coordinates. crop.scale(1 / scale); crop.offset(insets.left, insets.top); 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 a0d83c03da67b..dda6b2230ba25 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 @@ -242,17 +242,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private @Surface.Rotation int mCurrentRotation; - /** - * If set to {@code true}, no entering PiP transition would be kicked off and most likely - * it's due to the fact that Launcher is handling the transition directly when swiping - * auto PiP-able Activity to home. - * See also {@link #startSwipePipToHome(ComponentName, ActivityInfo, PictureInPictureParams)}. - */ - private boolean mInSwipePipToHomeTransition; - /** * An optional overlay used to mask content changing between an app in/out of PiP, only set if - * {@link #mInSwipePipToHomeTransition} is true. + * {@link PipTransitionState#getInSwipePipToHomeTransition()} is true. */ private SurfaceControl mSwipePipToHomeOverlay; @@ -343,7 +335,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, */ public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo, PictureInPictureParams pictureInPictureParams) { - mInSwipePipToHomeTransition = true; + mPipTransitionState.setInSwipePipToHomeTransition(true); sendOnPipTransitionStarted(TRANSITION_DIRECTION_TO_PIP); setBoundsStateForEntry(componentName, pictureInPictureParams, activityInfo); return mPipBoundsAlgorithm.getEntryDestinationBounds(); @@ -356,7 +348,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds, SurfaceControl overlay) { // do nothing if there is no startSwipePipToHome being called before - if (mInSwipePipToHomeTransition) { + if (mPipTransitionState.getInSwipePipToHomeTransition()) { mPipBoundsState.setBounds(destinationBounds); mSwipePipToHomeOverlay = overlay; } @@ -517,7 +509,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mOnDisplayIdChangeCallback.accept(info.displayId); } - if (mInSwipePipToHomeTransition) { + if (mPipTransitionState.getInSwipePipToHomeTransition()) { if (!mWaitForFixedRotation) { onEndOfSwipePipToHomeTransition(); } else { @@ -626,7 +618,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private void onEndOfSwipePipToHomeTransition() { if (Transitions.ENABLE_SHELL_TRANSITIONS) { - mInSwipePipToHomeTransition = false; + mPipTransitionState.setInSwipePipToHomeTransition(false); mSwipePipToHomeOverlay = null; return; } @@ -650,7 +642,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, null /* callback */, false /* withStartDelay */); } }, tx); - mInSwipePipToHomeTransition = false; + mPipTransitionState.setInSwipePipToHomeTransition(false); mSwipePipToHomeOverlay = null; } @@ -718,7 +710,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, return; } clearWaitForFixedRotation(); - mInSwipePipToHomeTransition = false; + mPipTransitionState.setInSwipePipToHomeTransition(false); mPictureInPictureParams = null; mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED); // Re-set the PIP bounds to none. @@ -793,7 +785,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, return; } if (mPipTransitionState.getTransitionState() == PipTransitionState.TASK_APPEARED) { - if (mInSwipePipToHomeTransition) { + if (mPipTransitionState.getInSwipePipToHomeTransition()) { onEndOfSwipePipToHomeTransition(); } else { // Schedule a regular animation to ensure all the callbacks are still being sent. @@ -859,10 +851,12 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, // Skip this entirely if that's the case. final boolean waitForFixedRotationOnEnteringPip = mWaitForFixedRotation && (mPipTransitionState.getTransitionState() != PipTransitionState.ENTERED_PIP); - if ((mInSwipePipToHomeTransition || waitForFixedRotationOnEnteringPip) && fromRotation) { + if ((mPipTransitionState.getInSwipePipToHomeTransition() + || waitForFixedRotationOnEnteringPip) && fromRotation) { if (DEBUG) { Log.d(TAG, "Skip onMovementBoundsChanged on rotation change" - + " mInSwipePipToHomeTransition=" + mInSwipePipToHomeTransition + + " InSwipePipToHomeTransition=" + + mPipTransitionState.getInSwipePipToHomeTransition() + " mWaitForFixedRotation=" + mWaitForFixedRotation + " getTransitionState=" + mPipTransitionState.getTransitionState()); } 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 18153e3f4246a..ae17a93ef1dc9 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 @@ -18,6 +18,7 @@ package com.android.wm.shell.pip; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; +import static android.util.RotationUtils.deltaRotation; import static android.view.WindowManager.TRANSIT_PIP; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; @@ -151,7 +152,8 @@ public class PipTransition extends PipTransitionController { mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP); mFinishCallback = finishCallback; return startEnterAnimation(enterPip.getTaskInfo(), enterPip.getLeash(), - startTransaction, finishTransaction); + startTransaction, finishTransaction, enterPip.getStartRotation(), + enterPip.getEndRotation()); } @Nullable @@ -208,7 +210,8 @@ public class PipTransition extends PipTransitionController { private boolean startEnterAnimation(final TaskInfo taskInfo, final SurfaceControl leash, final SurfaceControl.Transaction startTransaction, - final SurfaceControl.Transaction finishTransaction) { + final SurfaceControl.Transaction finishTransaction, + final int startRotation, final int endRotation) { setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams, taskInfo.topActivityInfo); final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); @@ -216,7 +219,8 @@ public class PipTransition extends PipTransitionController { PipAnimationController.PipTransitionAnimator animator; finishTransaction.setPosition(leash, destinationBounds.left, destinationBounds.top); if (taskInfo.pictureInPictureParams != null - && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) { + && taskInfo.pictureInPictureParams.isAutoEnterEnabled() + && mPipTransitionState.getInSwipePipToHomeTransition()) { mOneShotAnimationType = ANIM_TYPE_BOUNDS; // PiP menu is attached late in the process here to avoid any artifacts on the leash @@ -234,13 +238,21 @@ public class PipTransition extends PipTransitionController { mFinishCallback = null; return true; } + + int rotationDelta = deltaRotation(endRotation, startRotation); + if (rotationDelta != Surface.ROTATION_0) { + Matrix tmpTransform = new Matrix(); + tmpTransform.postRotate(rotationDelta == Surface.ROTATION_90 + ? Surface.ROTATION_270 : Surface.ROTATION_90); + startTransaction.setMatrix(leash, tmpTransform, new float[9]); + } if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( taskInfo.pictureInPictureParams, currentBounds); animator = mPipAnimationController.getAnimator(taskInfo, leash, currentBounds, currentBounds, destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP, - 0 /* startingAngle */, Surface.ROTATION_0); + 0 /* startingAngle */, rotationDelta); } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { startTransaction.setAlpha(leash, 0f); // PiP menu is attached late in the process here to avoid any artifacts on the leash @@ -258,6 +270,7 @@ public class PipTransition extends PipTransitionController { .setPipAnimationCallback(mPipAnimationCallback) .setDuration(mEnterExitAnimationDuration) .start(); + return true; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java index d23aada4133c1..85e56b7dd99f5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionState.java @@ -17,6 +17,9 @@ package com.android.wm.shell.pip; import android.annotation.IntDef; +import android.app.PictureInPictureParams; +import android.content.ComponentName; +import android.content.pm.ActivityInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -34,6 +37,15 @@ public class PipTransitionState { public static final int ENTERED_PIP = 4; public static final int EXITING_PIP = 5; + /** + * If set to {@code true}, no entering PiP transition would be kicked off and most likely + * it's due to the fact that Launcher is handling the transition directly when swiping + * auto PiP-able Activity to home. + * See also {@link PipTaskOrganizer#startSwipePipToHome(ComponentName, ActivityInfo, + * PictureInPictureParams)}. + */ + private boolean mInSwipePipToHomeTransition; + // Not a complete set of states but serves what we want right now. @IntDef(prefix = { "TRANSITION_STATE_" }, value = { UNDEFINED, @@ -65,6 +77,13 @@ public class PipTransitionState { && mState != EXITING_PIP; } + public void setInSwipePipToHomeTransition(boolean inSwipePipToHomeTransition) { + mInSwipePipToHomeTransition = inSwipePipToHomeTransition; + } + + public boolean getInSwipePipToHomeTransition() { + return mInSwipePipToHomeTransition; + } /** * Resize request can be initiated in other component, ignore if we are no longer in PIP, * still waiting for animation or we're exiting from it. diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java index 7e95e7d2aa8c4..4f7c9a4ccf1b3 100644 --- a/services/core/java/com/android/server/wm/PinnedTaskController.java +++ b/services/core/java/com/android/server/wm/PinnedTaskController.java @@ -211,7 +211,9 @@ class PinnedTaskController { } mFreezingTaskConfig = true; mDestRotatedBounds = new Rect(bounds); - continueOrientationChange(); + if (!mService.mAtmService.getTransitionController().isShellTransitionsEnabled()) { + continueOrientationChange(); + } } /** diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 5ffe7b6eaf6db..c962e065fc05b 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4634,7 +4634,8 @@ class Task extends TaskFragment { // From fullscreen to PiP. if (topActivity != null && currentMode == WINDOWING_MODE_FULLSCREEN - && windowingMode == WINDOWING_MODE_PINNED) { + && windowingMode == WINDOWING_MODE_PINNED + && !mAtmService.getTransitionController().isShellTransitionsEnabled()) { mDisplayContent.mPinnedTaskController .deferOrientationChangeForEnteringPipFromFullScreenIfNeeded(); }