Scale the leash for expand/collpase PiP transition

Screenshot: http://go/recall/~/AiNKCdFJI/efMwmlmBcsI6SpTGbpbHiZ

Bug: 150810705
Test: manually expand/collpase PiP window
Change-Id: Ie0c16c9eec65bce690fa67f80b551f3d8df0c3e9
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index 4bfcf22..232c23d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -110,10 +110,6 @@
         return mCurrentAnimator;
     }
 
-    PipTransitionAnimator getCurrentAnimator() {
-        return mCurrentAnimator;
-    }
-
     private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) {
         animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
         animator.setInterpolator(mFastOutSlowInInterpolator);
@@ -178,7 +174,7 @@
         @Override
         public void onAnimationStart(Animator animation) {
             mCurrentValue = mStartValue;
-            applySurfaceControlTransaction(mLeash, newSurfaceControlTransaction(), FRACTION_START);
+            onStartTransaction(mLeash, newSurfaceControlTransaction());
             if (mPipAnimationCallback != null) {
                 mPipAnimationCallback.onPipAnimationStart(this);
             }
@@ -194,7 +190,7 @@
         public void onAnimationEnd(Animator animation) {
             mCurrentValue = mEndValue;
             final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
-            applySurfaceControlTransaction(mLeash, tx, FRACTION_END);
+            onEndTransaction(mLeash, tx);
             if (mPipAnimationCallback != null) {
                 mPipAnimationCallback.onPipAnimationEnd(tx, this);
             }
@@ -253,6 +249,13 @@
             return mTransitionDirection != TRANSITION_DIRECTION_TO_FULLSCREEN;
         }
 
+        boolean inScaleTransition() {
+            if (mAnimationType != ANIM_TYPE_BOUNDS) return false;
+            final int direction = getTransitionDirection();
+            return direction != TRANSITION_DIRECTION_TO_FULLSCREEN
+                    && direction != TRANSITION_DIRECTION_TO_PIP;
+        }
+
         /**
          * Updates the {@link #mEndValue}.
          *
@@ -284,6 +287,10 @@
             mSurfaceTransactionHelper = helper;
         }
 
+        void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {}
+
+        void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {}
+
         abstract void applySurfaceControlTransaction(SurfaceControl leash,
                 SurfaceControl.Transaction tx, float fraction);
 
@@ -297,11 +304,14 @@
                     final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction;
                     setCurrentValue(alpha);
                     getSurfaceTransactionHelper().alpha(tx, leash, alpha);
-                    if (Float.compare(fraction, FRACTION_START) == 0) {
-                        getSurfaceTransactionHelper()
-                                .crop(tx, leash, getDestinationBounds())
-                                .round(tx, leash, shouldApplyCornerRadius());
-                    }
+                    tx.apply();
+                }
+
+                @Override
+                void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
+                    getSurfaceTransactionHelper()
+                            .crop(tx, leash, getDestinationBounds())
+                            .round(tx, leash, shouldApplyCornerRadius());
                     tx.apply();
                 }
             };
@@ -329,15 +339,30 @@
                             getCastedFractionValue(start.right, end.right, fraction),
                             getCastedFractionValue(start.bottom, end.bottom, fraction));
                     setCurrentValue(mTmpRect);
-                    getSurfaceTransactionHelper().crop(tx, leash, mTmpRect);
-                    if (Float.compare(fraction, FRACTION_START) == 0) {
-                        // Ensure the start condition
-                        getSurfaceTransactionHelper()
-                                .alpha(tx, leash, 1f)
-                                .round(tx, leash, shouldApplyCornerRadius());
+                    if (inScaleTransition()) {
+                        getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
+                    } else {
+                        getSurfaceTransactionHelper().crop(tx, leash, mTmpRect);
                     }
                     tx.apply();
                 }
+
+                @Override
+                void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
+                    getSurfaceTransactionHelper()
+                            .alpha(tx, leash, 1f)
+                            .round(tx, leash, shouldApplyCornerRadius());
+                    tx.apply();
+                }
+
+                @Override
+                void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
+                    if (!inScaleTransition()) return;
+                    // NOTE: intentionally does not apply the transaction here.
+                    // this end transaction should get executed synchronously with the final
+                    // WindowContainerTransaction in task organizer
+                    getSurfaceTransactionHelper().resetScale(tx, leash, getDestinationBounds());
+                }
             };
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java
index 21f9301..8001e49 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java
@@ -18,7 +18,9 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.view.SurfaceControl;
 
 import com.android.systemui.R;
@@ -35,6 +37,12 @@
     private final boolean mEnableCornerRadius;
     private final int mCornerRadius;
 
+    /** for {@link #scale(SurfaceControl.Transaction, SurfaceControl, Rect, Rect)} operation */
+    private final Matrix mTmpTransform = new Matrix();
+    private final float[] mTmpFloat9 = new float[9];
+    private final RectF mTmpSourceRectF = new RectF();
+    private final RectF mTmpDestinationRectF = new RectF();
+
     @Inject
     public PipSurfaceTransactionHelper(Context context) {
         final Resources res = context.getResources();
@@ -64,6 +72,31 @@
     }
 
     /**
+     * Operates the scale (setMatrix) on a given transaction and leash
+     * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
+     */
+    PipSurfaceTransactionHelper scale(SurfaceControl.Transaction tx, SurfaceControl leash,
+            Rect sourceBounds, Rect destinationBounds) {
+        mTmpSourceRectF.set(sourceBounds);
+        mTmpDestinationRectF.set(destinationBounds);
+        mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
+        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
+                .setPosition(leash, destinationBounds.left, destinationBounds.top);
+        return this;
+    }
+
+    /**
+     * Resets the scale (setMatrix) on a given transaction and leash if there's any
+     * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
+     */
+    PipSurfaceTransactionHelper resetScale(SurfaceControl.Transaction tx, SurfaceControl leash,
+            Rect destinationBounds) {
+        tx.setMatrix(leash, Matrix.IDENTITY_MATRIX, mTmpFloat9)
+                .setPosition(leash, destinationBounds.left, destinationBounds.top);
+        return this;
+    }
+
+    /**
      * Operates the round corner radius on a given transaction and leash
      * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
      */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
index b863f14..0d66340 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 
+import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -179,6 +180,12 @@
         }
 
         @Override
+        public SurfaceControl.Transaction setMatrix(SurfaceControl leash, Matrix matrix,
+                float[] float9) {
+            return this;
+        }
+
+        @Override
         public void apply() {}
     }
 }