diff options
7 files changed, 188 insertions, 74 deletions
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java index eb7ef1478a90..62ca5c687a2a 100644 --- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java @@ -18,6 +18,7 @@ package com.android.wm.shell.shared.pip; import static android.util.TypedValue.COMPLEX_UNIT_DIP; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.content.res.TypedArray; @@ -170,26 +171,34 @@ public abstract class PipContentOverlay { private final Context mContext; private final int mAppIconSizePx; - private final Rect mAppBounds; + /** + * The bounds of the application window relative to the task leash. + */ + private final Rect mRelativeAppBounds; private final int mOverlayHalfSize; private final Matrix mTmpTransform = new Matrix(); private final float[] mTmpFloat9 = new float[9]; private Bitmap mBitmap; - public PipAppIconOverlay(Context context, Rect appBounds, Rect destinationBounds, - Drawable appIcon, int appIconSizePx) { + // TODO(b/356277166): add non-match_parent support on PIP2. + /** + * @param context the {@link Context} that contains the icon information + * @param relativeAppBounds the bounds of the app window frame relative to the task leash + * @param destinationBounds the bounds for rhe PIP task + * @param appIcon the app icon {@link Drawable} + * @param appIconSizePx the icon dimension in pixel + */ + public PipAppIconOverlay(@NonNull Context context, @NonNull Rect relativeAppBounds, + @NonNull Rect destinationBounds, @NonNull Drawable appIcon, int appIconSizePx) { mContext = context; final int maxAppIconSizePx = (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, MAX_APP_ICON_SIZE_DP, context.getResources().getDisplayMetrics()); mAppIconSizePx = Math.min(maxAppIconSizePx, appIconSizePx); - final int overlaySize = getOverlaySize(appBounds, destinationBounds); + final int overlaySize = getOverlaySize(relativeAppBounds, destinationBounds); mOverlayHalfSize = overlaySize >> 1; - - // When the activity is in the secondary split, make sure the scaling center is not - // offset. - mAppBounds = new Rect(0, 0, appBounds.width(), appBounds.height()); + mRelativeAppBounds = relativeAppBounds; mBitmap = Bitmap.createBitmap(overlaySize, overlaySize, Bitmap.Config.ARGB_8888); prepareAppIconOverlay(appIcon); @@ -206,9 +215,9 @@ public abstract class PipContentOverlay { * the overlay will be drawn with the max size of the start and end bounds in different * rotation. */ - public static int getOverlaySize(Rect appBounds, Rect destinationBounds) { - final int appWidth = appBounds.width(); - final int appHeight = appBounds.height(); + public static int getOverlaySize(Rect overlayBounds, Rect destinationBounds) { + final int appWidth = overlayBounds.width(); + final int appHeight = overlayBounds.height(); return Math.max(Math.max(appWidth, appHeight), Math.max(destinationBounds.width(), destinationBounds.height())) + 1; @@ -230,15 +239,15 @@ public abstract class PipContentOverlay { mTmpTransform.reset(); // In order for the overlay to always cover the pip window, the overlay may have a // size larger than the pip window. Make sure that app icon is at the center. - final int appBoundsCenterX = mAppBounds.centerX(); - final int appBoundsCenterY = mAppBounds.centerY(); + final int appBoundsCenterX = mRelativeAppBounds.centerX(); + final int appBoundsCenterY = mRelativeAppBounds.centerY(); mTmpTransform.setTranslate( appBoundsCenterX - mOverlayHalfSize, appBoundsCenterY - mOverlayHalfSize); // Scale back the bitmap with the pivot point at center. final float scale = Math.min( - (float) mAppBounds.width() / currentBounds.width(), - (float) mAppBounds.height() / currentBounds.height()); + (float) mRelativeAppBounds.width() / currentBounds.width(), + (float) mRelativeAppBounds.height() / currentBounds.height()); mTmpTransform.postScale(scale, scale, appBoundsCenterX, appBoundsCenterY); atomicTx.setMatrix(mLeash, mTmpTransform, mTmpFloat9) .setAlpha(mLeash, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2); 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 f060158766fe..4aeecbec7dfb 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 @@ -30,6 +30,7 @@ import android.annotation.NonNull; import android.app.TaskInfo; import android.content.Context; import android.content.pm.ActivityInfo; +import android.graphics.Point; import android.graphics.Rect; import android.os.SystemClock; import android.view.Surface; @@ -152,7 +153,6 @@ public class PipAnimationController { return mCurrentAnimator; } - @SuppressWarnings("unchecked") /** * Construct and return an animator that animates from the {@param startBounds} to the * {@param endBounds} with the given {@param direction}. If {@param direction} is type @@ -171,6 +171,7 @@ public class PipAnimationController { * leaving PiP to fullscreen, and the {@param endBounds} is the fullscreen bounds before the * rotation change. */ + @SuppressWarnings("unchecked") @VisibleForTesting public PipTransitionAnimator getAnimator(TaskInfo taskInfo, SurfaceControl leash, Rect baseBounds, Rect startBounds, Rect endBounds, Rect sourceHintRect, @@ -566,7 +567,7 @@ public class PipAnimationController { } getSurfaceTransactionHelper() .resetScale(tx, leash, getDestinationBounds()) - .crop(tx, leash, getDestinationBounds()) + .cropAndPosition(tx, leash, getDestinationBounds()) .round(tx, leash, true /* applyCornerRadius */) .shadow(tx, leash, shouldApplyShadowRadius()); tx.show(leash); @@ -590,18 +591,50 @@ public class PipAnimationController { // Just for simplicity we'll interpolate between the source rect hint insets and empty // insets to calculate the window crop final Rect initialSourceValue; + final Rect mainWindowFrame = taskInfo.topActivityMainWindowFrame; + final boolean hasNonMatchFrame = mainWindowFrame != null; + final boolean changeOrientation = + rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270; + final Rect baseBounds = new Rect(baseValue); + final Rect startBounds = new Rect(startValue); + final Rect endBounds = new Rect(endValue); if (isOutPipDirection) { - initialSourceValue = new Rect(endValue); + // TODO(b/356277166): handle rotation change with activity that provides main window + // frame. + if (hasNonMatchFrame && !changeOrientation) { + endBounds.set(mainWindowFrame); + } + initialSourceValue = new Rect(endBounds); + } else if (isInPipDirection) { + if (hasNonMatchFrame) { + baseBounds.set(mainWindowFrame); + if (startValue.equals(baseValue)) { + // If the start value is at initial state as in PIP animation, also override + // the start bounds with nonMatchParentBounds. + startBounds.set(mainWindowFrame); + } + } + initialSourceValue = new Rect(baseBounds); } else { - initialSourceValue = new Rect(baseValue); + // Note that we assume the window bounds always match task bounds in PIP mode. + initialSourceValue = new Rect(baseBounds); + } + + final Point leashOffset; + if (isInPipDirection) { + leashOffset = new Point(baseValue.left, baseValue.top); + } else if (isOutPipDirection) { + leashOffset = new Point(endValue.left, endValue.top); + } else { + leashOffset = new Point(baseValue.left, baseValue.top); } final Rect rotatedEndRect; final Rect lastEndRect; final Rect initialContainerRect; - if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { - lastEndRect = new Rect(endValue); - rotatedEndRect = new Rect(endValue); + if (changeOrientation) { + lastEndRect = new Rect(endBounds); + rotatedEndRect = new Rect(endBounds); // Rotate the end bounds according to the rotation delta because the display will // be rotated to the same orientation. rotateBounds(rotatedEndRect, initialSourceValue, rotationDelta); @@ -617,9 +650,9 @@ public class PipAnimationController { // Crop a Rect matches the aspect ratio and pivots at the center point. // This is done for entering case only. if (isInPipDirection(direction)) { - final float aspectRatio = endValue.width() / (float) endValue.height(); + final float aspectRatio = endBounds.width() / (float) endBounds.height(); adjustedSourceRectHint.set(PipUtils.getEnterPipWithOverlaySrcRectHint( - startValue, aspectRatio)); + startBounds, aspectRatio)); } } else { adjustedSourceRectHint.set(sourceRectHint); @@ -644,7 +677,7 @@ public class PipAnimationController { // construct new Rect instances in case they are recycled return new PipTransitionAnimator<Rect>(taskInfo, leash, ANIM_TYPE_BOUNDS, - endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue)) { + endBounds, new Rect(baseBounds), new Rect(startBounds), new Rect(endBounds)) { private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect()); private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect()); @@ -668,11 +701,22 @@ public class PipAnimationController { setCurrentValue(bounds); if (inScaleTransition() || adjustedSourceRectHint.isEmpty()) { if (isOutPipDirection) { - getSurfaceTransactionHelper().crop(tx, leash, end) - .scale(tx, leash, end, bounds); + // Use the bounds relative to the task leash in case the leash does not + // start from (0, 0). + final Rect relativeEndBounds = new Rect(end); + relativeEndBounds.offset(-leashOffset.x, -leashOffset.y); + getSurfaceTransactionHelper() + .crop(tx, leash, relativeEndBounds) + .scale(tx, leash, relativeEndBounds, bounds, + false /* shouldOffset */); } else { - getSurfaceTransactionHelper().crop(tx, leash, base) - .scale(tx, leash, base, bounds, angle) + // TODO(b/356277166): add support to specify sourceRectHint with + // non-match parent activity. + // If there's a PIP resize animation, we should offset the bounds to + // (0, 0) since the window bounds should match the leash bounds in PIP + // mode. + getSurfaceTransactionHelper().cropAndPosition(tx, leash, base) + .scale(tx, leash, base, bounds, angle, inScaleTransition()) .round(tx, leash, base, bounds) .shadow(tx, leash, shouldApplyShadowRadius()); } @@ -680,7 +724,7 @@ public class PipAnimationController { final Rect insets = computeInsets(fraction); getSurfaceTransactionHelper().scaleAndCrop(tx, leash, adjustedSourceRectHint, initialSourceValue, bounds, insets, - isInPipDirection, fraction); + isInPipDirection, fraction, leashOffset); final Rect sourceBounds = new Rect(initialContainerRect); sourceBounds.inset(insets); getSurfaceTransactionHelper() @@ -733,8 +777,7 @@ public class PipAnimationController { getSurfaceTransactionHelper() .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection, - rotationDelta == ROTATION_270 /* clockwise */); - getSurfaceTransactionHelper() + rotationDelta == ROTATION_270 /* clockwise */) .round(tx, leash, sourceBounds, bounds) .shadow(tx, leash, shouldApplyShadowRadius()); if (!handlePipTransaction(leash, tx, bounds, 1f /* alpha */)) { @@ -772,7 +815,7 @@ public class PipAnimationController { tx.setPosition(leash, 0, 0); tx.setWindowCrop(leash, 0, 0); } else { - getSurfaceTransactionHelper().crop(tx, leash, destBounds); + getSurfaceTransactionHelper().cropAndPosition(tx, leash, destBounds); } if (mContentOverlay != null) { clearContentOverlay(); 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 3d1994cac534..b02bd0ffec6c 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 @@ -16,8 +16,10 @@ package com.android.wm.shell.pip; +import android.annotation.NonNull; import android.content.Context; import android.graphics.Matrix; +import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.view.Choreographer; @@ -68,52 +70,102 @@ public class PipSurfaceTransactionHelper { * Operates the crop (and position) on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ - public PipSurfaceTransactionHelper crop(SurfaceControl.Transaction tx, SurfaceControl leash, - Rect destinationBounds) { + public PipSurfaceTransactionHelper cropAndPosition(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect destinationBounds) { tx.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height()) .setPosition(leash, destinationBounds.left, destinationBounds.top); return this; } /** + * Operates {@link SurfaceControl.Transaction#setCrop} on a given transaction and leash. + * + * @param tx the transaction to apply + * @param leash the leash to crop + * @param relativeDestinationBounds the bounds to crop, which is relative to the leash + * coordinate + * @return same {@link PipSurfaceTransactionHelper} instance for method chaining + */ + public PipSurfaceTransactionHelper crop(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect relativeDestinationBounds) { + tx.setCrop(leash, relativeDestinationBounds); + return this; + } + + /** * Operates the scale (setMatrix) on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash, Rect sourceBounds, Rect destinationBounds) { mTmpDestinationRectF.set(destinationBounds); - return scale(tx, leash, sourceBounds, mTmpDestinationRectF, 0 /* degrees */); + return scale(tx, leash, sourceBounds, mTmpDestinationRectF, 0 /* degrees */, + true /* shouldOffset */); } /** * Operates the scale (setMatrix) on a given transaction and leash * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ - public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash, - Rect sourceBounds, RectF destinationBounds) { - return scale(tx, leash, sourceBounds, destinationBounds, 0 /* degrees */); + public PipSurfaceTransactionHelper scale(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect sourceBounds, + @NonNull RectF destinationBounds) { + return scale(tx, leash, sourceBounds, destinationBounds, 0 /* degrees */, + true /* shouldOffset */); } /** - * Operates the scale (setMatrix) on a given transaction and leash + * Operates the scale (setMatrix) on a given transaction and leash. + * + * @param shouldOffset {@code true} to offset the leash to (0, 0) * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ - public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash, - Rect sourceBounds, Rect destinationBounds, float degrees) { + public PipSurfaceTransactionHelper scale(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect sourceBounds, + @NonNull Rect destinationBounds, boolean shouldOffset) { + mTmpDestinationRectF.set(destinationBounds); + return scale(tx, leash, sourceBounds, mTmpDestinationRectF, 0 /* degrees */, shouldOffset); + } + + /** + * Operates the scale (setMatrix) on a given transaction and leash. + * + * @return same {@link PipSurfaceTransactionHelper} instance for method chaining + */ + public PipSurfaceTransactionHelper scale(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect sourceBounds, + @NonNull Rect destinationBounds, float degrees) { + return scale(tx, leash, sourceBounds, destinationBounds, degrees, true /* shouldOffset */); + } + + /** + * Operates the scale (setMatrix) on a given transaction and leash. + * + * @param shouldOffset {@code true} to offset the leash to (0, 0) + * @return same {@link PipSurfaceTransactionHelper} instance for method chaining + */ + public PipSurfaceTransactionHelper scale(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect sourceBounds, + @NonNull Rect destinationBounds, float degrees, boolean shouldOffset) { mTmpDestinationRectF.set(destinationBounds); - return scale(tx, leash, sourceBounds, mTmpDestinationRectF, degrees); + return scale(tx, leash, sourceBounds, mTmpDestinationRectF, degrees, shouldOffset); } /** * Operates the scale (setMatrix) on a given transaction and leash, along with a rotation. + * + * @param shouldOffset {@code true} to offset the leash to (0, 0) * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ - public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash, - Rect sourceBounds, RectF destinationBounds, float degrees) { + public PipSurfaceTransactionHelper scale(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect sourceBounds, + @NonNull RectF destinationBounds, float degrees, boolean shouldOffset) { mTmpSourceRectF.set(sourceBounds); // We want the matrix to position the surface relative to the screen coordinates so offset - // the source to 0,0 - mTmpSourceRectF.offsetTo(0, 0); + // the source to (0, 0) if {@code shouldOffset} is true. + if (shouldOffset) { + mTmpSourceRectF.offsetTo(0, 0); + } mTmpDestinationRectF.set(destinationBounds); mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL); mTmpTransform.postRotate(degrees, @@ -123,17 +175,19 @@ public class PipSurfaceTransactionHelper { } /** - * Operates the scale (setMatrix) on a given transaction and leash + * Operates the scale (setMatrix) on a given transaction and leash. + * + * @param leashOffset the offset of the leash bounds relative to the screen coordinate * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ - public PipSurfaceTransactionHelper scaleAndCrop(SurfaceControl.Transaction tx, - SurfaceControl leash, Rect sourceRectHint, - Rect sourceBounds, Rect destinationBounds, Rect insets, - boolean isInPipDirection, float fraction) { + public PipSurfaceTransactionHelper scaleAndCrop(@NonNull SurfaceControl.Transaction tx, + @NonNull SurfaceControl leash, @NonNull Rect sourceRectHint, @NonNull Rect sourceBounds, + @NonNull Rect destinationBounds, @NonNull Rect insets, boolean isInPipDirection, + float fraction, @NonNull Point leashOffset) { mTmpDestinationRect.set(sourceBounds); // Similar to {@link #scale}, we want to position the surface relative to the screen - // coordinates so offset the bounds to 0,0 - mTmpDestinationRect.offsetTo(0, 0); + // coordinates so offset the bounds relative to the leash. + mTmpDestinationRect.offset(-leashOffset.x, -leashOffset.y); mTmpDestinationRect.inset(insets); // Scale to the bounds no smaller than the destination and offset such that the top/left // of the scaled inset source rect aligns with the top/left of the destination bounds @@ -152,13 +206,13 @@ public class PipSurfaceTransactionHelper { scale = Math.max((float) destinationBounds.width() / sourceBounds.width(), (float) destinationBounds.height() / sourceBounds.height()); } - float left = destinationBounds.left - insets.left * scale; - float top = destinationBounds.top - insets.top * scale; + float left = destinationBounds.left - mTmpDestinationRect.left * scale; + float top = destinationBounds.top - mTmpDestinationRect.top * scale; if (scale == 1) { // Work around the 1 pixel off error by rounding the position down at very beginning. // We noticed such error from flicker tests, not visually. - left = sourceBounds.left; - top = sourceBounds.top; + left = leashOffset.x; + top = leashOffset.y; } mTmpTransform.setScale(scale, scale); tx.setMatrix(leash, mTmpTransform, mTmpFloat9) 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 b4e03299f14c..c4e63dfdade9 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 @@ -960,7 +960,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final SurfaceControl.Transaction boundsChangeTx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper - .crop(boundsChangeTx, mLeash, destinationBounds) + .cropAndPosition(boundsChangeTx, mLeash, destinationBounds) .round(boundsChangeTx, mLeash, true /* applyCornerRadius */); mPipTransitionState.setTransitionState(PipTransitionState.ENTRY_SCHEDULED); @@ -988,7 +988,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .resetScale(tx, mLeash, destinationBounds) - .crop(tx, mLeash, destinationBounds) + .cropAndPosition(tx, mLeash, destinationBounds) .round(tx, mLeash, isInPip()); // The animation is finished in the Launcher and here we directly apply the final touch. applyEnterPipSyncTransaction(destinationBounds, () -> { @@ -1525,7 +1525,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mPipBoundsState.setBounds(toBounds); final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper - .crop(tx, mLeash, toBounds) + .cropAndPosition(tx, mLeash, toBounds) .round(tx, mLeash, mPipTransitionState.isInPip()); if (shouldSyncPipTransactionWithMenu()) { mPipMenuController.resizePipMenu(mLeash, tx, toBounds); @@ -1628,7 +1628,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, Rect destinationBounds) { final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper - .crop(tx, mLeash, destinationBounds) + .cropAndPosition(tx, mLeash, destinationBounds) .resetScale(tx, mLeash, destinationBounds) .round(tx, mLeash, mPipTransitionState.isInPip()); return tx; 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 6da39951efbe..9aa5066fc76c 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 @@ -551,7 +551,7 @@ public class PipTransition extends PipTransitionController { } // Reset the scale with bounds change synchronously. if (hasValidLeash) { - mSurfaceTransactionHelper.crop(tx, leash, destinationBounds) + mSurfaceTransactionHelper.cropAndPosition(tx, leash, destinationBounds) .resetScale(tx, leash, destinationBounds) .round(tx, leash, true /* applyCornerRadius */); final Rect appBounds = mPipOrganizer.mAppBounds; @@ -588,7 +588,8 @@ public class PipTransition extends PipTransitionController { 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); + mSurfaceTransactionHelper.cropAndPosition(mFinishTransaction, leash, + finishBounds); } } mFinishTransaction = null; @@ -1068,6 +1069,11 @@ public class PipTransition extends PipTransitionController { mPipBoundsState.mayUseCachedLauncherShelfHeight(); final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); final Rect currentBounds = pipChange.getStartAbsBounds(); + // The app bounds should offset relative to the task leash to make the center calculation + // correctly. + final Rect relativeAppBounds = new Rect(taskInfo.topActivityMainWindowFrame != null + ? taskInfo.topActivityMainWindowFrame : currentBounds); + relativeAppBounds.offset(-currentBounds.left, -currentBounds.top); int rotationDelta = deltaRotation(startRotation, endRotation); Rect sourceHintRect = mPipOrganizer.takeSwipeSourceRectHint(); @@ -1089,6 +1095,8 @@ public class PipTransition extends PipTransitionController { if (taskInfo.pictureInPictureParams != null && taskInfo.pictureInPictureParams.isAutoEnterEnabled() && mPipTransitionState.getInSwipePipToHomeTransition()) { + // TODO(b/356277166): add support to swipe PIP to home with + // non-match parent activity. handleSwipePipToHomeTransition(startTransaction, finishTransaction, leash, sourceHintRect, destinationBounds, taskInfo); return; @@ -1119,8 +1127,8 @@ public class PipTransition extends PipTransitionController { // TODO(b/272819817): cleanup the null-check and extra logging. final boolean hasTopActivityInfo = taskInfo.topActivityInfo != null; if (hasTopActivityInfo && mFixedRotationState != FIXED_ROTATION_TRANSITION) { - animator.setAppIconContentOverlay( - mContext, currentBounds, destinationBounds, taskInfo.topActivityInfo, + animator.setAppIconContentOverlay(mContext, relativeAppBounds, + destinationBounds, taskInfo.topActivityInfo, mPipBoundsState.getLauncherState().getAppIconSizePx()); } else { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, @@ -1149,14 +1157,14 @@ public class PipTransition extends PipTransitionController { animationDuration = 0; } mSurfaceTransactionHelper - .crop(finishTransaction, leash, destinationBounds) + .cropAndPosition(finishTransaction, leash, destinationBounds) .round(finishTransaction, leash, true /* applyCornerRadius */); // Always reset to bounds animation type afterwards. setEnterAnimationType(ANIM_TYPE_BOUNDS); } else { throw new RuntimeException("Unrecognized animation type: " + enterAnimationType); } - mPipOrganizer.setContentOverlay(animator.getContentOverlayLeash(), currentBounds); + mPipOrganizer.setContentOverlay(animator.getContentOverlayLeash(), relativeAppBounds); animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP) .setPipAnimationCallback(mPipAnimationCallback) .setDuration(animationDuration); @@ -1340,11 +1348,11 @@ public class PipTransition extends PipTransitionController { "%s: Update pip for unhandled transition, change=%s, destBounds=%s, isInPip=%b", TAG, pipChange, destBounds, isInPip); mSurfaceTransactionHelper - .crop(startTransaction, leash, destBounds) + .cropAndPosition(startTransaction, leash, destBounds) .round(startTransaction, leash, isInPip) .shadow(startTransaction, leash, isInPip); mSurfaceTransactionHelper - .crop(finishTransaction, leash, destBounds) + .cropAndPosition(finishTransaction, leash, destBounds) .round(finishTransaction, leash, isInPip) .shadow(finishTransaction, leash, isInPip); // Make sure the PiP keeps invisible if it was faded out. If it needs to fade in, that will diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java index 7a0e6694cb51..affa6aaa5d07 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java @@ -338,7 +338,7 @@ public class TvPipTransition extends PipTransitionController { final Rect pipBounds = mPipBoundsState.getBounds(); mSurfaceTransactionHelper .resetScale(startTransaction, pipLeash, pipBounds) - .crop(startTransaction, pipLeash, pipBounds) + .cropAndPosition(startTransaction, pipLeash, pipBounds) .shadow(startTransaction, pipLeash, false); final SurfaceControl.Transaction transaction = mTransactionFactory.getTransaction(); @@ -420,7 +420,7 @@ public class TvPipTransition extends PipTransitionController { mSurfaceTransactionHelper .resetScale(finishTransaction, leash, pipBounds) - .crop(finishTransaction, leash, pipBounds) + .cropAndPosition(finishTransaction, leash, pipBounds) .shadow(finishTransaction, leash, false); final Rect currentBounds = pipChange.getStartAbsBounds(); @@ -443,7 +443,7 @@ public class TvPipTransition extends PipTransitionController { SurfaceControl.Transaction tx = mTransactionFactory.getTransaction(); mSurfaceTransactionHelper .resetScale(tx, leash, pipBounds) - .crop(tx, leash, pipBounds) + .cropAndPosition(tx, leash, pipBounds) .shadow(tx, leash, false); mShellTaskOrganizer.applyTransaction(resizePipWct); tx.apply(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index e74c804d4f40..bcb7461bfae7 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -280,7 +280,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { private void preparePipSurfaceTransactionHelper() { doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) - .crop(any(), any(), any()); + .cropAndPosition(any(), any(), any()); doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) .resetScale(any(), any(), any()); doReturn(mMockPipSurfaceTransactionHelper).when(mMockPipSurfaceTransactionHelper) |