PiP pinch-to-resize: Enable two finger movement and slight rotation.

Bug: 166478885
Test: Use two fingers and rotate and move PiP around
Change-Id: Ie9be757c95eb4bde66664ed3b8057b13f1d5bb5d
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index ea8a5c3..c0bc73d 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -17,4 +17,5 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.wm.shell">
+    <uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
 </manifest>
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 3362d2a..87f9d5b 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
@@ -116,7 +116,8 @@
      * 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
      * {@link ANIM_TYPE_BOUNDS}, then {@param sourceHintRect} will be used to animate
-     * in a better, more smooth manner.
+     * in a better, more smooth manner. If the original bound was rotated and a reset needs to
+     * happen, pass in {@param startingAngle}.
      *
      * In the case where one wants to start animation during an intermediate animation (for example,
      * if the user is currently doing a pinch-resize, and upon letting go now PiP needs to animate
@@ -128,11 +129,11 @@
     @VisibleForTesting
     public PipTransitionAnimator getAnimator(SurfaceControl leash, Rect baseBounds,
             Rect startBounds, Rect endBounds, Rect sourceHintRect,
-            @PipAnimationController.TransitionDirection int direction) {
+            @PipAnimationController.TransitionDirection int direction, float startingAngle) {
         if (mCurrentAnimator == null) {
             mCurrentAnimator = setupPipTransitionAnimator(
                     PipTransitionAnimator.ofBounds(leash, startBounds, startBounds, endBounds,
-                            sourceHintRect, direction));
+                            sourceHintRect, direction, 0 /* startingAngle */));
         } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                 && mCurrentAnimator.isRunning()) {
             // If we are still animating the fade into pip, then just move the surface and ensure
@@ -148,7 +149,7 @@
             mCurrentAnimator.cancel();
             mCurrentAnimator = setupPipTransitionAnimator(
                     PipTransitionAnimator.ofBounds(leash, baseBounds, startBounds, endBounds,
-                            sourceHintRect, direction));
+                            sourceHintRect, direction, startingAngle));
         }
         return mCurrentAnimator;
     }
@@ -201,6 +202,7 @@
         protected T mCurrentValue;
         protected T mStartValue;
         private T mEndValue;
+        private float mStartingAngle;
         private PipAnimationCallback mPipAnimationCallback;
         private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
                 mSurfaceControlTransactionFactory;
@@ -208,13 +210,15 @@
         private @TransitionDirection int mTransitionDirection;
 
         private PipTransitionAnimator(SurfaceControl leash, @AnimationType int animationType,
-                Rect destinationBounds, T baseValue, T startValue, T endValue) {
+                Rect destinationBounds, T baseValue, T startValue, T endValue,
+                float startingAngle) {
             mLeash = leash;
             mAnimationType = animationType;
             mDestinationBounds.set(destinationBounds);
             mBaseValue = baseValue;
             mStartValue = startValue;
             mEndValue = endValue;
+            mStartingAngle = startingAngle;
             addListener(this);
             addUpdateListener(this);
             mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
@@ -363,7 +367,7 @@
         static PipTransitionAnimator<Float> ofAlpha(SurfaceControl leash,
                 Rect destinationBounds, float startValue, float endValue) {
             return new PipTransitionAnimator<Float>(leash, ANIM_TYPE_ALPHA,
-                    destinationBounds, startValue, startValue, endValue) {
+                    destinationBounds, startValue, startValue, endValue, 0) {
                 @Override
                 void applySurfaceControlTransaction(SurfaceControl leash,
                         SurfaceControl.Transaction tx, float fraction) {
@@ -397,7 +401,7 @@
 
         static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
                 Rect baseValue, Rect startValue, Rect endValue, Rect sourceHintRect,
-                @PipAnimationController.TransitionDirection int direction) {
+                @PipAnimationController.TransitionDirection int direction, float startingAngle) {
             // Just for simplicity we'll interpolate between the source rect hint insets and empty
             // insets to calculate the window crop
             final Rect initialSourceValue;
@@ -420,7 +424,8 @@
 
             // construct new Rect instances in case they are recycled
             return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
-                    endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue)) {
+                    endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue),
+                    startingAngle) {
                 private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
                 private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
 
@@ -431,13 +436,14 @@
                     final Rect start = getStartValue();
                     final Rect end = getEndValue();
                     Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
+                    float angle = (1.0f - fraction) * startingAngle;
                     setCurrentValue(bounds);
                     if (inScaleTransition() || sourceHintRect == null) {
 
                         if (isOutPipDirection(direction)) {
                             getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
                         } else {
-                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds);
+                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle);
                         }
                     } else {
                         final Rect insets;
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 b9a5536..5224bcc 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
@@ -84,9 +84,19 @@
      */
     public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash,
             Rect sourceBounds, Rect destinationBounds) {
+        return scale(tx, leash, sourceBounds, destinationBounds, 0 /* degrees */);
+    }
+
+    /**
+     * Operates the scale (setMatrix) on a given transaction and leash, along with a rotation.
+     * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
+     */
+    public PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash,
+            Rect sourceBounds, Rect destinationBounds, float degrees) {
         mTmpSourceRectF.set(sourceBounds);
         mTmpDestinationRectF.set(destinationBounds);
         mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
+        mTmpTransform.postRotate(degrees);
         tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                 .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
         return this;
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 801ee2b..f43f44b 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
@@ -195,9 +195,10 @@
                 Rect currentBounds = (Rect) args.arg2;
                 Rect toBounds = (Rect) args.arg3;
                 Rect sourceHintRect = (Rect) args.arg4;
+                float startingAngle = (float) args.arg5;
                 int duration = args.argi2;
                 animateResizePip(currentBounds, toBounds, sourceHintRect,
-                        args.argi1 /* direction */, duration);
+                        args.argi1 /* direction */, duration, startingAngle);
                 if (updateBoundsCallback != null) {
                     updateBoundsCallback.accept(toBounds);
                 }
@@ -227,7 +228,8 @@
             case MSG_RESIZE_USER: {
                 Rect startBounds = (Rect) args.arg2;
                 Rect toBounds = (Rect) args.arg3;
-                userResizePip(startBounds, toBounds);
+                float degrees = (float) args.arg4;
+                userResizePip(startBounds, toBounds, degrees);
                 if (updateBoundsCallback != null) {
                     updateBoundsCallback.accept(toBounds);
                 }
@@ -427,7 +429,7 @@
                     final Rect sourceHintRect = getValidSourceHintRect(mPictureInPictureParams,
                             destinationBounds);
                     scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds,
-                            sourceHintRect, direction, animationDurationMs,
+                            0 /* startingAngle */, sourceHintRect, direction, animationDurationMs,
                             null /* updateBoundsCallback */);
                     mState = State.EXITING_PIP;
                 }
@@ -535,8 +537,8 @@
             mPipMenuController.attach(mLeash);
             final Rect sourceHintRect = getValidSourceHintRect(info.pictureInPictureParams,
                     currentBounds);
-            scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
-                    TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
+            scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */,
+                    sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
                     null /* updateBoundsCallback */);
             mState = State.ENTERING_PIP;
         } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
@@ -822,8 +824,9 @@
             Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
             return;
         }
-        scheduleAnimateResizePip(mPipBoundsState.getBounds(), toBounds, null /* sourceHintRect */,
-                TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
+        scheduleAnimateResizePip(mPipBoundsState.getBounds(), toBounds, 0 /* startingAngle */,
+                null /* sourceHintRect */, TRANSITION_DIRECTION_NONE, duration,
+                updateBoundsCallback);
     }
 
     /**
@@ -831,18 +834,23 @@
      * This is used when the starting bounds is not the current PiP bounds.
      */
     public void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration,
-            Consumer<Rect> updateBoundsCallback) {
+            float startingAngle, Consumer<Rect> updateBoundsCallback) {
         if (mWaitForFixedRotation) {
             Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
             return;
         }
-        scheduleAnimateResizePip(fromBounds, toBounds, null /* sourceHintRect */,
+        scheduleAnimateResizePip(fromBounds, toBounds, startingAngle, null /* sourceHintRect */,
                 TRANSITION_DIRECTION_SNAP_AFTER_RESIZE, duration, updateBoundsCallback);
     }
 
+    /**
+     * Animates resizing of the pinned stack given the duration and start bounds.
+     * This always animates the angle to zero from the starting angle.
+     */
     private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
-            Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
-            int durationMs, Consumer<Rect> updateBoundsCallback) {
+            float startingAngle, Rect sourceHintRect,
+            @PipAnimationController.TransitionDirection int direction, int durationMs,
+            Consumer<Rect> updateBoundsCallback) {
         if (!mState.isInPip()) {
             // TODO: tend to use shouldBlockResizeRequest here as well but need to consider
             // the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
@@ -855,6 +863,7 @@
         args.arg2 = currentBounds;
         args.arg3 = destinationBounds;
         args.arg4 = sourceHintRect;
+        args.arg5 = startingAngle;
         args.argi1 = direction;
         args.argi2 = durationMs;
         mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
@@ -872,15 +881,25 @@
     }
 
     /**
+     * Directly perform manipulation/resize on the leash, along with rotation. This will not perform
+     * any {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called.
+     */
+    public void scheduleUserResizePip(Rect startBounds, Rect toBounds,
+            Consumer<Rect> updateBoundsCallback) {
+        scheduleUserResizePip(startBounds, toBounds, 0 /* degrees */, updateBoundsCallback);
+    }
+
+    /**
      * Directly perform a scaled matrix transformation on the leash. This will not perform any
      * {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called.
      */
-    public void scheduleUserResizePip(Rect startBounds, Rect toBounds,
+    public void scheduleUserResizePip(Rect startBounds, Rect toBounds, float degrees,
             Consumer<Rect> updateBoundsCallback) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = updateBoundsCallback;
         args.arg2 = startBounds;
         args.arg3 = toBounds;
+        args.arg4 = degrees;
         mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_USER, args));
     }
 
@@ -959,7 +978,7 @@
         final Rect destinationBounds = new Rect(originalBounds);
         destinationBounds.offset(xOffset, yOffset);
         animateResizePip(originalBounds, destinationBounds, null /* sourceHintRect */,
-                TRANSITION_DIRECTION_SAME, durationMs);
+                TRANSITION_DIRECTION_SAME, durationMs, 0);
     }
 
     private void resizePip(Rect destinationBounds) {
@@ -985,7 +1004,7 @@
         }
     }
 
-    private void userResizePip(Rect startBounds, Rect destinationBounds) {
+    private void userResizePip(Rect startBounds, Rect destinationBounds, float degrees) {
         if (Looper.myLooper() != mUpdateHandler.getLooper()) {
             throw new RuntimeException("Callers should call scheduleUserResizePip() instead of "
                     + "this directly");
@@ -1002,7 +1021,7 @@
         }
 
         final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
-        mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, destinationBounds);
+        mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, destinationBounds, degrees);
         if (mPipMenuController.isMenuVisible()) {
             runOnMainHandler(() ->
                     mPipMenuController.movePipMenu(mLeash, tx, destinationBounds));
@@ -1089,7 +1108,8 @@
     }
 
     private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
-            @PipAnimationController.TransitionDirection int direction, int durationMs) {
+            @PipAnimationController.TransitionDirection int direction, int durationMs,
+            float startingAngle) {
         if (Looper.myLooper() != mUpdateHandler.getLooper()) {
             throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
                     + "this directly");
@@ -1103,7 +1123,7 @@
                 ? mPipBoundsState.getBounds() : currentBounds;
         mPipAnimationController
                 .getAnimator(mLeash, baseBounds, currentBounds, destinationBounds, sourceHintRect,
-                        direction)
+                        direction, startingAngle)
                 .setTransitionDirection(direction)
                 .setPipAnimationCallback(mPipAnimationCallback)
                 .setDuration(durationMs)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
index 721f621..805123f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipPinchResizingAlgorithm.java
@@ -53,6 +53,8 @@
         final float aspect = (float) width / (float) height;
         final int widthDelta = Math.round(Math.abs(x0 - x1) - Math.abs(downx0 - downx1));
         final int heightDelta = Math.round(Math.abs(y0 - y1) - Math.abs(downy0 - downy1));
+        final int dx = (int) ((x0 - downx0 + x1 - downx1) / 2);
+        final int dy = (int) ((y0 - downy0 + y1 - downy1) / 2);
 
         width = Math.max(minVisibleWidth, Math.min(width + widthDelta, maxSize.x));
         height = Math.max(minVisibleHeight, Math.min(height + heightDelta, maxSize.y));
@@ -118,6 +120,7 @@
                 currentPipBounds.centerY() - height / 2,
                 currentPipBounds.centerX() + width / 2,
                 currentPipBounds.centerY() + height / 2);
+        TMP_RECT.offset(dx, dy);
         return TMP_RECT;
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 02f6231c..1f6df3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -62,6 +62,7 @@
 
     private static final String TAG = "PipResizeGestureHandler";
     private static final int PINCH_RESIZE_SNAP_DURATION = 250;
+    private static final int PINCH_RESIZE_MAX_ANGLE_ROTATION = 45;
 
     private final Context mContext;
     private final PipBoundsAlgorithm mPipBoundsAlgorithm;
@@ -359,12 +360,12 @@
             if (mFirstIndex == -1 && mSecondIndex == -1) {
                 mFirstIndex = 0;
                 mSecondIndex = 1;
-                mLastResizeBounds.setEmpty();
                 mDownPoint.set(ev.getRawX(mFirstIndex), ev.getRawY(mFirstIndex));
                 mDownSecondaryPoint.set(ev.getRawX(mSecondIndex), ev.getRawY(mSecondIndex));
 
-                mLastResizeBounds.setEmpty();
+
                 mLastDownBounds.set(mPipBoundsState.getBounds());
+                mLastResizeBounds.set(mLastDownBounds);
             }
         }
 
@@ -403,18 +404,63 @@
                 x1 = mThresholdCrossed1 ? x1 : mDownSecondaryPoint.x;
                 y1 = mThresholdCrossed1 ? y1 : mDownSecondaryPoint.y;
 
-                final Rect currentPipBounds = mPipBoundsState.getBounds();
+                final Rect originalPipBounds = mPipBoundsState.getBounds();
+                int focusX = (int) originalPipBounds.centerX();
+                int focusY = (int) originalPipBounds.centerY();
+
+                float down0X = mDownPoint.x;
+                float down0Y = mDownPoint.y;
+                float down1X = mDownSecondaryPoint.x;
+                float down1Y = mDownSecondaryPoint.y;
+
+                // Top right + Bottom left pinch to zoom.
+                if ((down0X > focusX && down0Y < focusY && down1X < focusX && down1Y > focusY)
+                        || (down1X > focusX && down1Y < focusY
+                        && down0X < focusX && down0Y > focusY)) {
+                    mAngle = calculateRotationAngle(mLastResizeBounds.centerX(),
+                            mLastResizeBounds.centerY(), x0, y0, x1, y1, true);
+                } else if ((down0X < focusX && down0Y < focusY
+                        && down1X > focusX && down1Y > focusY)
+                        || (down1X < focusX && down1Y < focusY
+                        && down0X > focusX && down0Y > focusY)) {
+                    mAngle = calculateRotationAngle(mLastResizeBounds.centerX(),
+                            mLastResizeBounds.centerY(), x0, y0, x1, y1, false);
+                }
+
                 mLastResizeBounds.set(PipPinchResizingAlgorithm.pinchResize(x0, y0, x1, y1,
                         mDownPoint.x, mDownPoint.y, mDownSecondaryPoint.x, mDownSecondaryPoint.y,
-                        currentPipBounds, mMinSize.x, mMinSize.y, mMaxSize));
+                        originalPipBounds, mMinSize.x, mMinSize.y, mMaxSize));
 
                 mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
-                        null);
+                        (float) -mAngle, null);
                 mPipBoundsState.setHasUserResizedPip(true);
             }
         }
     }
 
+    private float mAngle = 0;
+
+    private float calculateRotationAngle(int focusX, int focusY, float x0, float y0,
+            float x1, float y1, boolean positive) {
+
+        // The base angle is the angle formed by taking the angle between the center horizontal
+        // and one of the corners.
+        double baseAngle = Math.toDegrees(Math.atan2(Math.abs(mLastResizeBounds.top - focusY),
+                Math.abs(mLastResizeBounds.right - focusX)));
+        double angle0 = mThresholdCrossed0
+                ? Math.toDegrees(Math.atan2(Math.abs(y0 - focusY), Math.abs(x0 - focusX)))
+                : baseAngle;
+        double angle1 = mThresholdCrossed1
+                ? Math.toDegrees(Math.atan2(Math.abs(y1 - focusY), Math.abs(x1 - focusX)))
+                : baseAngle;
+
+        // Calculate the percentage difference of [0, 90] compare to the base angle.
+        double diff0 = (Math.max(0, Math.min(angle0, 90)) - baseAngle) / 90;
+        double diff1 = (Math.max(0, Math.min(angle1, 90)) - baseAngle) / 90;
+
+        return (float) (diff0 + diff1) / 2 * PINCH_RESIZE_MAX_ANGLE_ROTATION * (positive ? 1 : -1);
+    }
+
     private void onDragCornerResize(MotionEvent ev) {
         int action = ev.getActionMasked();
         float x = ev.getX();
@@ -490,7 +536,7 @@
                 mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds,
                         mPipBoundsAlgorithm.getSnapFraction(mPipBoundsState.getBounds()));
                 mPipTaskOrganizer.scheduleAnimateResizePip(startBounds, mLastResizeBounds,
-                        PINCH_RESIZE_SNAP_DURATION,
+                        PINCH_RESIZE_SNAP_DURATION, mAngle,
                         (Rect rect) -> {
                             mHandler.post(callback);
                         });
@@ -509,6 +555,7 @@
 
     private void resetState() {
         mCtrlType = CTRL_NONE;
+        mAngle = 0;
         mUsingPinchToZoom = false;
         mAllowGesture = false;
         mThresholdCrossed = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index 6a26eab..75d674e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -63,6 +63,7 @@
     private static final String TAG = "PipTouchHandler";
 
     private static final float STASH_MINIMUM_VELOCITY_X = 3000.f;
+    private static final float MINIMUM_SIZE_PERCENT = 0.4f;
 
     // Allow PIP to resize to a slightly bigger state upon touch
     private final boolean mEnableResize;
@@ -438,17 +439,17 @@
             float aspectRatio) {
         final int shorterLength = Math.min(mPipBoundsState.getDisplayBounds().width(),
                 mPipBoundsState.getDisplayBounds().height());
-        final int padding = insetBounds.left;
+        final int totalPadding = insetBounds.left * 2;
         final int minWidth, minHeight, maxWidth, maxHeight;
         if (aspectRatio > 1f) {
-            minWidth = (int) Math.min(normalBounds.width(), shorterLength * 0.4);
+            minWidth = (int) Math.min(normalBounds.width(), shorterLength * MINIMUM_SIZE_PERCENT);
             minHeight = (int) (minWidth / aspectRatio);
-            maxWidth = (int) Math.max(normalBounds.width(), shorterLength - 2 * padding);
+            maxWidth = (int) Math.max(normalBounds.width(), shorterLength - totalPadding);
             maxHeight = (int) (maxWidth / aspectRatio);
         } else {
-            minHeight = (int) Math.min(normalBounds.height(), shorterLength * 0.4);
+            minHeight = (int) Math.min(normalBounds.height(), shorterLength * MINIMUM_SIZE_PERCENT);
             minWidth = (int) (minHeight * aspectRatio);
-            maxHeight = (int) Math.max(normalBounds.height(), shorterLength - 2 * padding);
+            maxHeight = (int) Math.max(normalBounds.height(), shorterLength - totalPadding);
             maxWidth = (int) (maxHeight * aspectRatio);
         }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index d30fa38..c565a4c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -80,7 +80,7 @@
     public void getAnimator_withBounds_returnBoundsAnimator() {
         final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
                 .getAnimator(mLeash, new Rect(), new Rect(), new Rect(), null,
-                        TRANSITION_DIRECTION_TO_PIP);
+                        TRANSITION_DIRECTION_TO_PIP, 0);
 
         assertEquals("Expect ANIM_TYPE_BOUNDS animation",
                 animator.getAnimationType(), PipAnimationController.ANIM_TYPE_BOUNDS);
@@ -94,13 +94,13 @@
         final Rect endValue2 = new Rect(200, 200, 300, 300);
         final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
                 .getAnimator(mLeash, baseValue, startValue, endValue1, null,
-                        TRANSITION_DIRECTION_TO_PIP);
+                        TRANSITION_DIRECTION_TO_PIP, 0);
         oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
         oldAnimator.start();
 
         final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
                 .getAnimator(mLeash, baseValue, startValue, endValue2, null,
-                        TRANSITION_DIRECTION_TO_PIP);
+                        TRANSITION_DIRECTION_TO_PIP, 0);
 
         assertEquals("getAnimator with same type returns same animator",
                 oldAnimator, newAnimator);
@@ -132,7 +132,7 @@
         final Rect endValue2 = new Rect(200, 200, 300, 300);
         final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
                 .getAnimator(mLeash, baseValue, startValue, endValue1, null,
-                        TRANSITION_DIRECTION_TO_PIP);
+                        TRANSITION_DIRECTION_TO_PIP, 0);
 
         animator.updateEndValue(endValue2);
 
@@ -146,7 +146,7 @@
         final Rect endValue = new Rect(100, 100, 200, 200);
         final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
                 .getAnimator(mLeash, baseValue, startValue, endValue, null,
-                        TRANSITION_DIRECTION_TO_PIP);
+                        TRANSITION_DIRECTION_TO_PIP, 0);
         animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
 
         animator.setPipAnimationCallback(mPipAnimationCallback);