Merge "Restore support for source hint rect" into rvc-dev am: 2776d3e91a am: 72bc5ff462

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11713503

Change-Id: I491599964eedfc467a676be235376104aa4ca3e4
This commit is contained in:
Winson Chung
2020-06-05 07:08:20 +00:00
committed by Automerger Merge Worker
5 changed files with 104 additions and 46 deletions

View File

@@ -17,6 +17,7 @@
package com.android.systemui.pip; package com.android.systemui.pip;
import android.animation.Animator; import android.animation.Animator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.content.Context; import android.content.Context;
@@ -26,6 +27,7 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Interpolators;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@@ -74,15 +76,12 @@ public class PipAnimationController {
|| direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN; || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
} }
private final Interpolator mFastOutSlowInInterpolator;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private PipTransitionAnimator mCurrentAnimator; private PipTransitionAnimator mCurrentAnimator;
@Inject @Inject
PipAnimationController(Context context, PipSurfaceTransactionHelper helper) { PipAnimationController(Context context, PipSurfaceTransactionHelper helper) {
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mSurfaceTransactionHelper = helper; mSurfaceTransactionHelper = helper;
} }
@@ -104,10 +103,11 @@ public class PipAnimationController {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds) { PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds,
Rect sourceHintRect) {
if (mCurrentAnimator == null) { if (mCurrentAnimator == null) {
mCurrentAnimator = setupPipTransitionAnimator( mCurrentAnimator = setupPipTransitionAnimator(
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds)); PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
&& mCurrentAnimator.isRunning()) { && mCurrentAnimator.isRunning()) {
// If we are still animating the fade into pip, then just move the surface and ensure // If we are still animating the fade into pip, then just move the surface and ensure
@@ -122,7 +122,7 @@ public class PipAnimationController {
} else { } else {
mCurrentAnimator.cancel(); mCurrentAnimator.cancel();
mCurrentAnimator = setupPipTransitionAnimator( mCurrentAnimator = setupPipTransitionAnimator(
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds)); PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
} }
return mCurrentAnimator; return mCurrentAnimator;
} }
@@ -133,7 +133,7 @@ public class PipAnimationController {
private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) { private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) {
animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper); animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
animator.setInterpolator(mFastOutSlowInInterpolator); animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
animator.setFloatValues(FRACTION_START, FRACTION_END); animator.setFloatValues(FRACTION_START, FRACTION_END);
return animator; return animator;
} }
@@ -331,6 +331,7 @@ public class PipAnimationController {
@Override @Override
void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) { void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
getSurfaceTransactionHelper() getSurfaceTransactionHelper()
.resetScale(tx, leash, getDestinationBounds())
.crop(tx, leash, getDestinationBounds()) .crop(tx, leash, getDestinationBounds())
.round(tx, leash, shouldApplyCornerRadius()); .round(tx, leash, shouldApplyCornerRadius());
tx.show(leash); tx.show(leash);
@@ -346,35 +347,46 @@ public class PipAnimationController {
} }
static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash, static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
Rect startValue, Rect endValue) { Rect startValue, Rect endValue, Rect sourceHintRect) {
// Just for simplicity we'll interpolate between the source rect hint insets and empty
// insets to calculate the window crop
final Rect initialStartValue = new Rect(startValue);
final Rect sourceHintRectInsets = sourceHintRect != null
? new Rect(sourceHintRect.left - startValue.left,
sourceHintRect.top - startValue.top,
startValue.right - sourceHintRect.right,
startValue.bottom - sourceHintRect.bottom)
: null;
final Rect sourceInsets = new Rect(0, 0, 0, 0);
// construct new Rect instances in case they are recycled // construct new Rect instances in case they are recycled
return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS, return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
endValue, new Rect(startValue), new Rect(endValue)) { endValue, new Rect(startValue), new Rect(endValue)) {
private final Rect mTmpRect = new Rect(); private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
private int getCastedFractionValue(float start, float end, float fraction) {
return (int) (start * (1 - fraction) + end * fraction + .5f);
}
@Override @Override
void applySurfaceControlTransaction(SurfaceControl leash, void applySurfaceControlTransaction(SurfaceControl leash,
SurfaceControl.Transaction tx, float fraction) { SurfaceControl.Transaction tx, float fraction) {
final Rect start = getStartValue(); final Rect start = getStartValue();
final Rect end = getEndValue(); final Rect end = getEndValue();
mTmpRect.set( Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
getCastedFractionValue(start.left, end.left, fraction), setCurrentValue(bounds);
getCastedFractionValue(start.top, end.top, fraction),
getCastedFractionValue(start.right, end.right, fraction),
getCastedFractionValue(start.bottom, end.bottom, fraction));
setCurrentValue(mTmpRect);
if (inScaleTransition()) { if (inScaleTransition()) {
if (isOutPipDirection(getTransitionDirection())) { if (isOutPipDirection(getTransitionDirection())) {
getSurfaceTransactionHelper().scale(tx, leash, end, mTmpRect); getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
} else { } else {
getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect); getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
} }
} else { } else {
getSurfaceTransactionHelper().crop(tx, leash, mTmpRect); if (sourceHintRectInsets != null) {
Rect insets = mInsetsEvaluator.evaluate(fraction, sourceInsets,
sourceHintRectInsets);
getSurfaceTransactionHelper().scaleAndCrop(tx, leash, initialStartValue,
bounds, insets);
} else {
getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
}
} }
tx.apply(); tx.apply();
} }
@@ -390,11 +402,11 @@ public class PipAnimationController {
@Override @Override
void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) { void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
if (!inScaleTransition()) return;
// NOTE: intentionally does not apply the transaction here. // NOTE: intentionally does not apply the transaction here.
// this end transaction should get executed synchronously with the final // this end transaction should get executed synchronously with the final
// WindowContainerTransaction in task organizer // WindowContainerTransaction in task organizer
getSurfaceTransactionHelper().resetScale(tx, leash, getDestinationBounds()) getSurfaceTransactionHelper()
.resetScale(tx, leash, getDestinationBounds())
.crop(tx, leash, getDestinationBounds()); .crop(tx, leash, getDestinationBounds());
} }

View File

@@ -296,6 +296,14 @@ public class PipBoundsHandler {
*/ */
public boolean onDisplayRotationChanged(Rect outBounds, Rect oldBounds, Rect outInsetBounds, public boolean onDisplayRotationChanged(Rect outBounds, Rect oldBounds, Rect outInsetBounds,
int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) { int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) {
// Calculate the snap fraction of the current stack along the old movement bounds
final Rect postChangeStackBounds = new Rect(oldBounds);
final float snapFraction = getSnapFraction(postChangeStackBounds);
// Update the display layout, note that we have to do this on every rotation even if we
// aren't in PIP since we need to update the display layout to get the right resources
mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
// Bail early if the event is not sent to current {@link #mDisplayInfo} // Bail early if the event is not sent to current {@link #mDisplayInfo}
if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) { if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) {
return false; return false;
@@ -312,13 +320,6 @@ public class PipBoundsHandler {
return false; return false;
} }
// Calculate the snap fraction of the current stack along the old movement bounds
final Rect postChangeStackBounds = new Rect(oldBounds);
final float snapFraction = getSnapFraction(postChangeStackBounds);
// Update the display layout
mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
// Populate the new {@link #mDisplayInfo}. // Populate the new {@link #mDisplayInfo}.
// The {@link DisplayInfo} queried from DisplayManager would be the one before rotation, // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
// therefore, the width/height may require a swap first. // therefore, the width/height may require a swap first.

View File

@@ -44,6 +44,7 @@ public class PipSurfaceTransactionHelper implements ConfigurationController.Conf
private final float[] mTmpFloat9 = new float[9]; private final float[] mTmpFloat9 = new float[9];
private final RectF mTmpSourceRectF = new RectF(); private final RectF mTmpSourceRectF = new RectF();
private final RectF mTmpDestinationRectF = new RectF(); private final RectF mTmpDestinationRectF = new RectF();
private final Rect mTmpDestinationRect = new Rect();
@Inject @Inject
public PipSurfaceTransactionHelper(Context context, ConfigurationController configController) { public PipSurfaceTransactionHelper(Context context, ConfigurationController configController) {
@@ -90,7 +91,30 @@ public class PipSurfaceTransactionHelper implements ConfigurationController.Conf
mTmpDestinationRectF.set(destinationBounds); mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL); mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9) tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, destinationBounds.left, destinationBounds.top); .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
return this;
}
/**
* Operates the scale (setMatrix) on a given transaction and leash
* @return same {@link PipSurfaceTransactionHelper} instance for method chaining
*/
PipSurfaceTransactionHelper scaleAndCrop(SurfaceControl.Transaction tx, SurfaceControl leash,
Rect sourceBounds, Rect destinationBounds, Rect insets) {
mTmpSourceRectF.set(sourceBounds);
mTmpDestinationRect.set(sourceBounds);
mTmpDestinationRect.inset(insets);
// Scale by the shortest edge and offset such that the top/left of the scaled inset source
// rect aligns with the top/left of the destination bounds
final float scale = sourceBounds.width() <= sourceBounds.height()
? (float) destinationBounds.width() / sourceBounds.width()
: (float) destinationBounds.height() / sourceBounds.height();
final float left = destinationBounds.left - insets.left * scale;
final float top = destinationBounds.top - insets.top * scale;
mTmpTransform.setScale(scale, scale);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, left, top);
return this; return this;
} }

View File

@@ -143,8 +143,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements
case MSG_RESIZE_ANIMATE: { case MSG_RESIZE_ANIMATE: {
Rect currentBounds = (Rect) args.arg2; Rect currentBounds = (Rect) args.arg2;
Rect toBounds = (Rect) args.arg3; Rect toBounds = (Rect) args.arg3;
Rect sourceHintRect = (Rect) args.arg4;
int duration = args.argi2; int duration = args.argi2;
animateResizePip(currentBounds, toBounds, args.argi1 /* direction */, duration); animateResizePip(currentBounds, toBounds, sourceHintRect,
args.argi1 /* direction */, duration);
if (updateBoundsCallback != null) { if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds); updateBoundsCallback.accept(toBounds);
} }
@@ -294,7 +296,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
public void onTransactionReady(int id, SurfaceControl.Transaction t) { public void onTransactionReady(int id, SurfaceControl.Transaction t) {
t.apply(); t.apply();
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds, scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
direction, animationDurationMs, null /* updateBoundsCallback */); null /* sourceHintRect */, direction, animationDurationMs,
null /* updateBoundsCallback */);
mInPip = false; mInPip = false;
} }
}); });
@@ -357,7 +360,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds(); final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
scheduleAnimateResizePip(currentBounds, destinationBounds, final Rect sourceHintRect = getValidSourceHintRect(info, currentBounds);
scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
null /* updateBoundsCallback */); null /* updateBoundsCallback */);
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
@@ -368,6 +372,21 @@ public class PipTaskOrganizer extends TaskOrganizer implements
} }
} }
/**
* Returns the source hint rect if it is valid (if provided and is contained by the current
* task bounds).
*/
private Rect getValidSourceHintRect(ActivityManager.RunningTaskInfo info, Rect sourceBounds) {
final Rect sourceHintRect = info.pictureInPictureParams != null
&& info.pictureInPictureParams.hasSourceBoundsHint()
? info.pictureInPictureParams.getSourceRectHint()
: null;
if (sourceHintRect != null && sourceBounds.contains(sourceHintRect)) {
return sourceHintRect;
}
return null;
}
private void enterPipWithAlphaAnimation(Rect destinationBounds, long durationMs) { private void enterPipWithAlphaAnimation(Rect destinationBounds, long durationMs) {
// If we are fading the PIP in, then we should move the pip to the final location as // If we are fading the PIP in, then we should move the pip to the final location as
// soon as possible, but set the alpha immediately since the transaction can take a // soon as possible, but set the alpha immediately since the transaction can take a
@@ -552,13 +571,13 @@ public class PipTaskOrganizer extends TaskOrganizer implements
Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred"); Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
return; return;
} }
scheduleAnimateResizePip(mLastReportedBounds, toBounds, scheduleAnimateResizePip(mLastReportedBounds, toBounds, null /* sourceHintRect */,
TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback); TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
} }
private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds, private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction, int durationMs, Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
Consumer<Rect> updateBoundsCallback) { int durationMs, Consumer<Rect> updateBoundsCallback) {
if (!mInPip) { if (!mInPip) {
// can be initiated in other component, ignore if we are no longer in PIP // can be initiated in other component, ignore if we are no longer in PIP
return; return;
@@ -568,6 +587,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
args.arg1 = updateBoundsCallback; args.arg1 = updateBoundsCallback;
args.arg2 = currentBounds; args.arg2 = currentBounds;
args.arg3 = destinationBounds; args.arg3 = destinationBounds;
args.arg4 = sourceHintRect;
args.argi1 = direction; args.argi1 = direction;
args.argi2 = durationMs; args.argi2 = durationMs;
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args)); mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
@@ -667,7 +687,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
} }
final Rect destinationBounds = new Rect(originalBounds); final Rect destinationBounds = new Rect(originalBounds);
destinationBounds.offset(xOffset, yOffset); destinationBounds.offset(xOffset, yOffset);
animateResizePip(originalBounds, destinationBounds, TRANSITION_DIRECTION_SAME, durationMs); animateResizePip(originalBounds, destinationBounds, null /* sourceHintRect */,
TRANSITION_DIRECTION_SAME, durationMs);
} }
private void resizePip(Rect destinationBounds) { private void resizePip(Rect destinationBounds) {
@@ -745,7 +766,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
WindowOrganizer.applyTransaction(wct); WindowOrganizer.applyTransaction(wct);
} }
private void animateResizePip(Rect currentBounds, Rect destinationBounds, private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
@PipAnimationController.TransitionDirection int direction, int durationMs) { @PipAnimationController.TransitionDirection int direction, int durationMs) {
if (Looper.myLooper() != mUpdateHandler.getLooper()) { if (Looper.myLooper() != mUpdateHandler.getLooper()) {
throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of " throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
@@ -757,7 +778,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
return; return;
} }
mPipAnimationController mPipAnimationController
.getAnimator(mLeash, currentBounds, destinationBounds) .getAnimator(mLeash, currentBounds, destinationBounds, sourceHintRect)
.setTransitionDirection(direction) .setTransitionDirection(direction)
.setPipAnimationCallback(mPipAnimationCallback) .setPipAnimationCallback(mPipAnimationCallback)
.setDuration(durationMs) .setDuration(durationMs)

View File

@@ -82,7 +82,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
@Test @Test
public void getAnimator_withBounds_returnBoundsAnimator() { public void getAnimator_withBounds_returnBoundsAnimator() {
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, new Rect(), new Rect()); .getAnimator(mLeash, new Rect(), new Rect(), null);
assertEquals("Expect ANIM_TYPE_BOUNDS animation", assertEquals("Expect ANIM_TYPE_BOUNDS animation",
animator.getAnimationType(), PipAnimationController.ANIM_TYPE_BOUNDS); animator.getAnimationType(), PipAnimationController.ANIM_TYPE_BOUNDS);
@@ -94,12 +94,12 @@ public class PipAnimationControllerTest extends SysuiTestCase {
final Rect endValue1 = new Rect(100, 100, 200, 200); final Rect endValue1 = new Rect(100, 100, 200, 200);
final Rect endValue2 = new Rect(200, 200, 300, 300); final Rect endValue2 = new Rect(200, 200, 300, 300);
final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
.getAnimator(mLeash, startValue, endValue1); .getAnimator(mLeash, startValue, endValue1, null);
oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new); oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
oldAnimator.start(); oldAnimator.start();
final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
.getAnimator(mLeash, startValue, endValue2); .getAnimator(mLeash, startValue, endValue2, null);
assertEquals("getAnimator with same type returns same animator", assertEquals("getAnimator with same type returns same animator",
oldAnimator, newAnimator); oldAnimator, newAnimator);
@@ -129,7 +129,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
final Rect endValue1 = new Rect(100, 100, 200, 200); final Rect endValue1 = new Rect(100, 100, 200, 200);
final Rect endValue2 = new Rect(200, 200, 300, 300); final Rect endValue2 = new Rect(200, 200, 300, 300);
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, startValue, endValue1); .getAnimator(mLeash, startValue, endValue1, null);
animator.updateEndValue(endValue2); animator.updateEndValue(endValue2);
@@ -141,7 +141,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
final Rect startValue = new Rect(0, 0, 100, 100); final Rect startValue = new Rect(0, 0, 100, 100);
final Rect endValue = new Rect(100, 100, 200, 200); final Rect endValue = new Rect(100, 100, 200, 200);
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
.getAnimator(mLeash, startValue, endValue); .getAnimator(mLeash, startValue, endValue, null);
animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new); animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
animator.setPipAnimationCallback(mPipAnimationCallback); animator.setPipAnimationCallback(mPipAnimationCallback);