diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java index 4bfcf2229e3e1..232c23dc14f0c 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 @@ public class PipAnimationController { return mCurrentAnimator; } - PipTransitionAnimator getCurrentAnimator() { - return mCurrentAnimator; - } - private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) { animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper); animator.setInterpolator(mFastOutSlowInInterpolator); @@ -178,7 +174,7 @@ public class PipAnimationController { @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 class PipAnimationController { 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 @@ public class PipAnimationController { 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 @@ public class PipAnimationController { 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 @@ public class PipAnimationController { 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 @@ public class PipAnimationController { 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 21f9301fe7942..8001e497794a8 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 @@ package com.android.systemui.pip; 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 @@ public class PipSurfaceTransactionHelper { 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(); @@ -63,6 +71,31 @@ public class PipSurfaceTransactionHelper { return this; } + /** + * 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 b863f143056fa..0d66340a39172 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.any; 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; @@ -178,6 +179,12 @@ public class PipAnimationControllerTest extends SysuiTestCase { return this; } + @Override + public SurfaceControl.Transaction setMatrix(SurfaceControl leash, Matrix matrix, + float[] float9) { + return this; + } + @Override public void apply() {} }