summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/pip/PipContentOverlay.java39
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java79
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java104
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipTransition.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java2
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)