Merge "Revert "Revert "Restore support for source hint rect""" into rvc-dev
This commit is contained in:
@@ -18,16 +18,16 @@ package com.android.systemui.pip;
|
||||
|
||||
import android.animation.AnimationHandler;
|
||||
import android.animation.Animator;
|
||||
import android.animation.RectEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.IntDef;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
|
||||
import com.android.systemui.Interpolators;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -76,7 +76,6 @@ public class PipAnimationController {
|
||||
|| direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
|
||||
}
|
||||
|
||||
private final Interpolator mFastOutSlowInInterpolator;
|
||||
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
|
||||
|
||||
private PipTransitionAnimator mCurrentAnimator;
|
||||
@@ -90,8 +89,6 @@ public class PipAnimationController {
|
||||
|
||||
@Inject
|
||||
PipAnimationController(Context context, PipSurfaceTransactionHelper helper) {
|
||||
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
|
||||
com.android.internal.R.interpolator.fast_out_slow_in);
|
||||
mSurfaceTransactionHelper = helper;
|
||||
}
|
||||
|
||||
@@ -113,10 +110,11 @@ public class PipAnimationController {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds) {
|
||||
PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds,
|
||||
Rect sourceHintRect) {
|
||||
if (mCurrentAnimator == null) {
|
||||
mCurrentAnimator = setupPipTransitionAnimator(
|
||||
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
|
||||
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
|
||||
} 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
|
||||
@@ -131,7 +129,7 @@ public class PipAnimationController {
|
||||
} else {
|
||||
mCurrentAnimator.cancel();
|
||||
mCurrentAnimator = setupPipTransitionAnimator(
|
||||
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
|
||||
PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
|
||||
}
|
||||
return mCurrentAnimator;
|
||||
}
|
||||
@@ -142,7 +140,7 @@ public class PipAnimationController {
|
||||
|
||||
private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) {
|
||||
animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
|
||||
animator.setInterpolator(mFastOutSlowInInterpolator);
|
||||
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||
animator.setFloatValues(FRACTION_START, FRACTION_END);
|
||||
animator.setAnimationHandler(mSfAnimationHandlerThreadLocal.get());
|
||||
return animator;
|
||||
@@ -341,6 +339,7 @@ public class PipAnimationController {
|
||||
@Override
|
||||
void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
|
||||
getSurfaceTransactionHelper()
|
||||
.resetScale(tx, leash, getDestinationBounds())
|
||||
.crop(tx, leash, getDestinationBounds())
|
||||
.round(tx, leash, shouldApplyCornerRadius());
|
||||
tx.show(leash);
|
||||
@@ -356,35 +355,46 @@ public class PipAnimationController {
|
||||
}
|
||||
|
||||
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
|
||||
return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
|
||||
endValue, new Rect(startValue), new Rect(endValue)) {
|
||||
private final Rect mTmpRect = new Rect();
|
||||
|
||||
private int getCastedFractionValue(float start, float end, float fraction) {
|
||||
return (int) (start * (1 - fraction) + end * fraction + .5f);
|
||||
}
|
||||
private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
|
||||
private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
|
||||
|
||||
@Override
|
||||
void applySurfaceControlTransaction(SurfaceControl leash,
|
||||
SurfaceControl.Transaction tx, float fraction) {
|
||||
final Rect start = getStartValue();
|
||||
final Rect end = getEndValue();
|
||||
mTmpRect.set(
|
||||
getCastedFractionValue(start.left, end.left, fraction),
|
||||
getCastedFractionValue(start.top, end.top, fraction),
|
||||
getCastedFractionValue(start.right, end.right, fraction),
|
||||
getCastedFractionValue(start.bottom, end.bottom, fraction));
|
||||
setCurrentValue(mTmpRect);
|
||||
Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
|
||||
setCurrentValue(bounds);
|
||||
if (inScaleTransition()) {
|
||||
if (isOutPipDirection(getTransitionDirection())) {
|
||||
getSurfaceTransactionHelper().scale(tx, leash, end, mTmpRect);
|
||||
getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
|
||||
} else {
|
||||
getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
|
||||
getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
|
||||
}
|
||||
} 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();
|
||||
}
|
||||
@@ -400,11 +410,11 @@ public class PipAnimationController {
|
||||
|
||||
@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())
|
||||
getSurfaceTransactionHelper()
|
||||
.resetScale(tx, leash, getDestinationBounds())
|
||||
.crop(tx, leash, getDestinationBounds());
|
||||
}
|
||||
|
||||
|
||||
@@ -288,6 +288,24 @@ public class PipBoundsHandler {
|
||||
return mDefaultAspectRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updatest the display info and display layout on rotation change. This is needed even when we
|
||||
* aren't in PIP because the rotation layout is used to calculate the proper insets for the
|
||||
* next enter animation into PIP.
|
||||
*/
|
||||
public void onDisplayRotationChangedNotInPip(int toRotation) {
|
||||
// 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);
|
||||
|
||||
// Populate the new {@link #mDisplayInfo}.
|
||||
// The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
|
||||
// therefore, the width/height may require a swap first.
|
||||
// Moving forward, we should get the new dimensions after rotation from DisplayLayout.
|
||||
mDisplayInfo.rotation = toRotation;
|
||||
updateDisplayInfoIfNeeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the display info, calculating and returning the new stack and movement bounds in the
|
||||
* new orientation of the device if necessary.
|
||||
|
||||
@@ -44,6 +44,7 @@ public class PipSurfaceTransactionHelper implements ConfigurationController.Conf
|
||||
private final float[] mTmpFloat9 = new float[9];
|
||||
private final RectF mTmpSourceRectF = new RectF();
|
||||
private final RectF mTmpDestinationRectF = new RectF();
|
||||
private final Rect mTmpDestinationRect = new Rect();
|
||||
|
||||
@Inject
|
||||
public PipSurfaceTransactionHelper(Context context, ConfigurationController configController) {
|
||||
@@ -90,7 +91,30 @@ public class PipSurfaceTransactionHelper implements ConfigurationController.Conf
|
||||
mTmpDestinationRectF.set(destinationBounds);
|
||||
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -143,8 +143,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
case MSG_RESIZE_ANIMATE: {
|
||||
Rect currentBounds = (Rect) args.arg2;
|
||||
Rect toBounds = (Rect) args.arg3;
|
||||
Rect sourceHintRect = (Rect) args.arg4;
|
||||
int duration = args.argi2;
|
||||
animateResizePip(currentBounds, toBounds, args.argi1 /* direction */, duration);
|
||||
animateResizePip(currentBounds, toBounds, sourceHintRect,
|
||||
args.argi1 /* direction */, duration);
|
||||
if (updateBoundsCallback != null) {
|
||||
updateBoundsCallback.accept(toBounds);
|
||||
}
|
||||
@@ -307,7 +309,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
|
||||
t.apply();
|
||||
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
|
||||
direction, animationDurationMs, null /* updateBoundsCallback */);
|
||||
null /* sourceHintRect */, direction, animationDurationMs,
|
||||
null /* updateBoundsCallback */);
|
||||
mInPip = false;
|
||||
}
|
||||
});
|
||||
@@ -380,7 +383,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
|
||||
|
||||
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
|
||||
scheduleAnimateResizePip(currentBounds, destinationBounds,
|
||||
final Rect sourceHintRect = getValidSourceHintRect(info, currentBounds);
|
||||
scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
|
||||
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
|
||||
null /* updateBoundsCallback */);
|
||||
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
||||
@@ -391,6 +395,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) {
|
||||
// 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
|
||||
@@ -611,13 +630,13 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
|
||||
return;
|
||||
}
|
||||
scheduleAnimateResizePip(mLastReportedBounds, toBounds,
|
||||
scheduleAnimateResizePip(mLastReportedBounds, toBounds, null /* sourceHintRect */,
|
||||
TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
|
||||
}
|
||||
|
||||
private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
|
||||
@PipAnimationController.TransitionDirection int direction, int durationMs,
|
||||
Consumer<Rect> updateBoundsCallback) {
|
||||
Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
|
||||
int durationMs, Consumer<Rect> updateBoundsCallback) {
|
||||
if (!mInPip) {
|
||||
// TODO: tend to use shouldBlockResizeRequest here as well but need to consider
|
||||
// the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
|
||||
@@ -629,6 +648,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
args.arg1 = updateBoundsCallback;
|
||||
args.arg2 = currentBounds;
|
||||
args.arg3 = destinationBounds;
|
||||
args.arg4 = sourceHintRect;
|
||||
args.argi1 = direction;
|
||||
args.argi2 = durationMs;
|
||||
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
|
||||
@@ -732,7 +752,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
}
|
||||
final Rect destinationBounds = new Rect(originalBounds);
|
||||
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) {
|
||||
@@ -838,7 +859,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
return WINDOWING_MODE_UNDEFINED;
|
||||
}
|
||||
|
||||
private void animateResizePip(Rect currentBounds, Rect destinationBounds,
|
||||
|
||||
private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
|
||||
@PipAnimationController.TransitionDirection int direction, int durationMs) {
|
||||
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
||||
throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
|
||||
@@ -850,7 +872,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
|
||||
return;
|
||||
}
|
||||
mPipAnimationController
|
||||
.getAnimator(mLeash, currentBounds, destinationBounds)
|
||||
.getAnimator(mLeash, currentBounds, destinationBounds, sourceHintRect)
|
||||
.setTransitionDirection(direction)
|
||||
.setPipAnimationCallback(mPipAnimationCallback)
|
||||
.setDuration(durationMs)
|
||||
|
||||
@@ -96,7 +96,9 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
||||
private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
|
||||
int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
|
||||
if (!mPipTaskOrganizer.isInPip() || mPipTaskOrganizer.isDeferringEnterPipAnimation()) {
|
||||
// Skip if we aren't in PIP or haven't actually entered PIP yet
|
||||
// Skip if we aren't in PIP or haven't actually entered PIP yet. We still need to update
|
||||
// the display layout in the bounds handler in this case.
|
||||
mPipBoundsHandler.onDisplayRotationChangedNotInPip(toRotation);
|
||||
return;
|
||||
}
|
||||
// If there is an animation running (ie. from a shelf offset), then ensure that we calculate
|
||||
|
||||
@@ -82,7 +82,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void getAnimator_withBounds_returnBoundsAnimator() {
|
||||
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
||||
.getAnimator(mLeash, new Rect(), new Rect());
|
||||
.getAnimator(mLeash, new Rect(), new Rect(), null);
|
||||
|
||||
assertEquals("Expect ANIM_TYPE_BOUNDS animation",
|
||||
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 endValue2 = new Rect(200, 200, 300, 300);
|
||||
final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
|
||||
.getAnimator(mLeash, startValue, endValue1);
|
||||
.getAnimator(mLeash, startValue, endValue1, null);
|
||||
oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
|
||||
oldAnimator.start();
|
||||
|
||||
final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
|
||||
.getAnimator(mLeash, startValue, endValue2);
|
||||
.getAnimator(mLeash, startValue, endValue2, null);
|
||||
|
||||
assertEquals("getAnimator with same type returns same animator",
|
||||
oldAnimator, newAnimator);
|
||||
@@ -129,7 +129,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
||||
final Rect endValue1 = new Rect(100, 100, 200, 200);
|
||||
final Rect endValue2 = new Rect(200, 200, 300, 300);
|
||||
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
||||
.getAnimator(mLeash, startValue, endValue1);
|
||||
.getAnimator(mLeash, startValue, endValue1, null);
|
||||
|
||||
animator.updateEndValue(endValue2);
|
||||
|
||||
@@ -141,7 +141,7 @@ public class PipAnimationControllerTest extends SysuiTestCase {
|
||||
final Rect startValue = new Rect(0, 0, 100, 100);
|
||||
final Rect endValue = new Rect(100, 100, 200, 200);
|
||||
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
|
||||
.getAnimator(mLeash, startValue, endValue);
|
||||
.getAnimator(mLeash, startValue, endValue, null);
|
||||
animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
|
||||
|
||||
animator.setPipAnimationCallback(mPipAnimationCallback);
|
||||
|
||||
Reference in New Issue
Block a user