Merge "Polish entering pip from fullscreen with shell transition" into udc-dev
This commit is contained in:
@@ -52,7 +52,7 @@ import java.util.Objects;
|
||||
*/
|
||||
public class PipAnimationController {
|
||||
static final float FRACTION_START = 0f;
|
||||
private static final float FRACTION_END = 1f;
|
||||
static final float FRACTION_END = 1f;
|
||||
|
||||
public static final int ANIM_TYPE_BOUNDS = 0;
|
||||
public static final int ANIM_TYPE_ALPHA = 1;
|
||||
@@ -718,7 +718,9 @@ public class PipAnimationController {
|
||||
.round(tx, leash, sourceBounds, bounds)
|
||||
.shadow(tx, leash, shouldApplyShadowRadius());
|
||||
}
|
||||
tx.apply();
|
||||
if (!handlePipTransaction(leash, tx, bounds, 1f /* alpha */)) {
|
||||
tx.apply();
|
||||
}
|
||||
}
|
||||
|
||||
private Rect computeInsets(float fraction) {
|
||||
|
||||
@@ -828,6 +828,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
|
||||
private void onEndOfSwipePipToHomeTransition() {
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
mPipTransitionController.setEnterAnimationType(ANIM_TYPE_BOUNDS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ import android.animation.Animator;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.IBinder;
|
||||
@@ -109,6 +108,17 @@ public class PipTransition extends PipTransitionController {
|
||||
/** Whether the PIP window has fade out for fixed rotation. */
|
||||
private boolean mHasFadeOut;
|
||||
|
||||
/** Used for setting transform to a transaction from animator. */
|
||||
private final PipAnimationController.PipTransactionHandler mTransactionConsumer =
|
||||
new PipAnimationController.PipTransactionHandler() {
|
||||
@Override
|
||||
public boolean handlePipTransaction(SurfaceControl leash,
|
||||
SurfaceControl.Transaction tx, Rect destinationBounds, float alpha) {
|
||||
// Only set the operation to transaction but do not apply.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public PipTransition(Context context,
|
||||
@NonNull ShellInit shellInit,
|
||||
@NonNull ShellTaskOrganizer shellTaskOrganizer,
|
||||
@@ -338,7 +348,7 @@ public class PipTransition extends PipTransitionController {
|
||||
@Override
|
||||
public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds,
|
||||
@PipAnimationController.TransitionDirection int direction,
|
||||
@Nullable SurfaceControl.Transaction tx) {
|
||||
@NonNull SurfaceControl.Transaction tx) {
|
||||
final boolean enteringPip = isInPipDirection(direction);
|
||||
if (enteringPip) {
|
||||
mPipTransitionState.setTransitionState(ENTERED_PIP);
|
||||
@@ -348,13 +358,15 @@ public class PipTransition extends PipTransitionController {
|
||||
// (likely a remote like launcher), so don't fire the finish-callback here -- wait until
|
||||
// the exit transition is merged.
|
||||
if ((mExitTransition == null || isAnimatingLocally()) && mFinishCallback != null) {
|
||||
final SurfaceControl leash = mPipOrganizer.getSurfaceControl();
|
||||
final boolean hasValidLeash = leash != null && leash.isValid();
|
||||
WindowContainerTransaction wct = null;
|
||||
if (isOutPipDirection(direction)) {
|
||||
// Only need to reset surface properties. The server-side operations were already
|
||||
// done at the start. But if it is running fixed rotation, there will be a seamless
|
||||
// display transition later. So the last rotation transform needs to be kept to
|
||||
// avoid flickering, and then the display transition will reset the transform.
|
||||
if (tx != null && !mInFixedRotation) {
|
||||
if (!mInFixedRotation && mFinishTransaction != null) {
|
||||
mFinishTransaction.merge(tx);
|
||||
}
|
||||
} else {
|
||||
@@ -363,27 +375,36 @@ public class PipTransition extends PipTransitionController {
|
||||
// If we are animating from fullscreen using a bounds animation, then reset the
|
||||
// activity windowing mode, and set the task bounds to the final bounds
|
||||
wct.setActivityWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
|
||||
wct.scheduleFinishEnterPip(taskInfo.token, destinationBounds);
|
||||
wct.setBounds(taskInfo.token, destinationBounds);
|
||||
} else {
|
||||
wct.setBounds(taskInfo.token, null /* bounds */);
|
||||
}
|
||||
if (tx != null) {
|
||||
wct.setBoundsChangeTransaction(taskInfo.token, tx);
|
||||
// Reset the scale with bounds change synchronously.
|
||||
if (hasValidLeash) {
|
||||
mSurfaceTransactionHelper.crop(tx, leash, destinationBounds)
|
||||
.resetScale(tx, leash, destinationBounds)
|
||||
.round(tx, leash, true /* applyCornerRadius */);
|
||||
}
|
||||
wct.setBoundsChangeTransaction(taskInfo.token, tx);
|
||||
}
|
||||
final SurfaceControl leash = mPipOrganizer.getSurfaceControl();
|
||||
final int displayRotation = taskInfo.getConfiguration().windowConfiguration
|
||||
.getDisplayRotation();
|
||||
if (enteringPip && mInFixedRotation && mEndFixedRotation != displayRotation
|
||||
&& leash != null && leash.isValid()) {
|
||||
&& hasValidLeash) {
|
||||
// Launcher may update the Shelf height during the animation, which will update the
|
||||
// destination bounds. Because this is in fixed rotation, We need to make sure the
|
||||
// finishTransaction is using the updated bounds in the display rotation.
|
||||
final PipAnimationController.PipTransitionAnimator<?> animator =
|
||||
mPipAnimationController.getCurrentAnimator();
|
||||
final Rect displayBounds = mPipDisplayLayoutState.getDisplayBounds();
|
||||
final Rect finishBounds = new Rect(destinationBounds);
|
||||
rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation);
|
||||
mSurfaceTransactionHelper.crop(mFinishTransaction, leash, finishBounds);
|
||||
if (!finishBounds.equals(animator.getEndValue())) {
|
||||
ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
|
||||
"%s: Destination bounds were changed during animation", TAG);
|
||||
rotateBounds(finishBounds, displayBounds, mEndFixedRotation, displayRotation);
|
||||
mSurfaceTransactionHelper.crop(mFinishTransaction, leash, finishBounds);
|
||||
}
|
||||
}
|
||||
mFinishTransaction = null;
|
||||
callFinishCallback(wct);
|
||||
@@ -665,9 +686,11 @@ public class PipTransition extends PipTransitionController {
|
||||
private void startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash,
|
||||
final Rect baseBounds, final Rect startBounds, final Rect endBounds,
|
||||
final int rotationDelta) {
|
||||
final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
|
||||
taskInfo.pictureInPictureParams, endBounds);
|
||||
final PipAnimationController.PipTransitionAnimator animator =
|
||||
mPipAnimationController.getAnimator(taskInfo, leash, baseBounds, startBounds,
|
||||
endBounds, null /* sourceHintRect */, TRANSITION_DIRECTION_LEAVE_PIP,
|
||||
endBounds, sourceHintRect, TRANSITION_DIRECTION_LEAVE_PIP,
|
||||
0 /* startingAngle */, rotationDelta);
|
||||
animator.setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP)
|
||||
.setPipAnimationCallback(mPipAnimationCallback)
|
||||
@@ -800,10 +823,6 @@ public class PipTransition extends PipTransitionController {
|
||||
computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo,
|
||||
destinationBounds, sourceHintRect);
|
||||
}
|
||||
// Set corner radius for entering pip.
|
||||
mSurfaceTransactionHelper
|
||||
.crop(finishTransaction, leash, destinationBounds)
|
||||
.round(finishTransaction, leash, true /* applyCornerRadius */);
|
||||
if (!mPipOrganizer.shouldAttachMenuEarly()) {
|
||||
mTransitions.getMainExecutor().executeDelayed(
|
||||
() -> mPipMenuController.attach(leash), 0);
|
||||
@@ -812,41 +831,11 @@ public class PipTransition extends PipTransitionController {
|
||||
if (taskInfo.pictureInPictureParams != null
|
||||
&& taskInfo.pictureInPictureParams.isAutoEnterEnabled()
|
||||
&& mPipTransitionState.getInSwipePipToHomeTransition()) {
|
||||
final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
|
||||
startTransaction.setMatrix(leash, Matrix.IDENTITY_MATRIX, new float[9])
|
||||
.setPosition(leash, destinationBounds.left, destinationBounds.top)
|
||||
.setWindowCrop(leash, destinationBounds.width(), destinationBounds.height());
|
||||
if (swipePipToHomeOverlay != null) {
|
||||
// Launcher fade in the overlay on top of the fullscreen Task. It is possible we
|
||||
// reparent the PIP activity to a new PIP task (in case there are other activities
|
||||
// in the original Task), so we should also reparent the overlay to the PIP task.
|
||||
startTransaction.reparent(swipePipToHomeOverlay, leash)
|
||||
.setLayer(swipePipToHomeOverlay, Integer.MAX_VALUE);
|
||||
mPipOrganizer.mSwipePipToHomeOverlay = null;
|
||||
}
|
||||
startTransaction.apply();
|
||||
if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
|
||||
// For fixed rotation, set the destination bounds to the new rotation coordinates
|
||||
// at the end.
|
||||
destinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds());
|
||||
}
|
||||
mPipBoundsState.setBounds(destinationBounds);
|
||||
onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, null /* tx */);
|
||||
sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
|
||||
if (swipePipToHomeOverlay != null) {
|
||||
mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay,
|
||||
null /* callback */, false /* withStartDelay */);
|
||||
}
|
||||
mPipTransitionState.setInSwipePipToHomeTransition(false);
|
||||
handleSwipePipToHomeTransition(startTransaction, finishTransaction, leash,
|
||||
sourceHintRect, destinationBounds, rotationDelta, taskInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rotationDelta != Surface.ROTATION_0) {
|
||||
Matrix tmpTransform = new Matrix();
|
||||
tmpTransform.postRotate(rotationDelta);
|
||||
startTransaction.setMatrix(leash, tmpTransform, new float[9]);
|
||||
}
|
||||
|
||||
final int enterAnimationType = mEnterAnimationType;
|
||||
if (enterAnimationType == ANIM_TYPE_ALPHA) {
|
||||
startTransaction.setAlpha(leash, 0f);
|
||||
@@ -880,11 +869,13 @@ public class PipTransition extends PipTransitionController {
|
||||
} else if (enterAnimationType == ANIM_TYPE_ALPHA) {
|
||||
animator = mPipAnimationController.getAnimator(taskInfo, leash, destinationBounds,
|
||||
0f, 1f);
|
||||
mSurfaceTransactionHelper
|
||||
.crop(finishTransaction, leash, destinationBounds)
|
||||
.round(finishTransaction, leash, true /* applyCornerRadius */);
|
||||
} else {
|
||||
throw new RuntimeException("Unrecognized animation type: " + enterAnimationType);
|
||||
}
|
||||
animator.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
|
||||
.setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler())
|
||||
.setPipAnimationCallback(mPipAnimationCallback)
|
||||
.setDuration(mEnterExitAnimationDuration);
|
||||
if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) {
|
||||
@@ -893,7 +884,15 @@ public class PipTransition extends PipTransitionController {
|
||||
// ComputeRotatedBounds has changed the DisplayLayout without affecting the animation.
|
||||
animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds());
|
||||
}
|
||||
animator.start();
|
||||
// Keep the last appearance when finishing the transition. The transform will be reset when
|
||||
// setting bounds.
|
||||
animator.setPipTransactionHandler(mTransactionConsumer).applySurfaceControlTransaction(
|
||||
leash, finishTransaction, PipAnimationController.FRACTION_END);
|
||||
// Remove the workaround after fixing ClosePipBySwipingDownTest that detects the shadow
|
||||
// as unexpected visible.
|
||||
finishTransaction.setShadowRadius(leash, 0);
|
||||
// Start to animate enter PiP.
|
||||
animator.setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler()).start();
|
||||
}
|
||||
|
||||
/** Computes destination bounds in old rotation and updates source hint rect if available. */
|
||||
@@ -915,6 +914,51 @@ public class PipTransition extends PipTransitionController {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSwipePipToHomeTransition(
|
||||
@NonNull SurfaceControl.Transaction startTransaction,
|
||||
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||
@NonNull SurfaceControl leash, @Nullable Rect sourceHintRect,
|
||||
@NonNull Rect destinationBounds, int rotationDelta,
|
||||
@NonNull ActivityManager.RunningTaskInfo pipTaskInfo) {
|
||||
final SurfaceControl swipePipToHomeOverlay = mPipOrganizer.mSwipePipToHomeOverlay;
|
||||
if (swipePipToHomeOverlay != null) {
|
||||
// Launcher fade in the overlay on top of the fullscreen Task. It is possible we
|
||||
// reparent the PIP activity to a new PIP task (in case there are other activities
|
||||
// in the original Task), so we should also reparent the overlay to the PIP task.
|
||||
startTransaction.reparent(swipePipToHomeOverlay, leash)
|
||||
.setLayer(swipePipToHomeOverlay, Integer.MAX_VALUE);
|
||||
mPipOrganizer.mSwipePipToHomeOverlay = null;
|
||||
}
|
||||
|
||||
Rect sourceBounds = pipTaskInfo.configuration.windowConfiguration.getBounds();
|
||||
if (!Transitions.SHELL_TRANSITIONS_ROTATION && rotationDelta % 2 == 1) {
|
||||
// PipController#startSwipePipToHome has updated the display layout to new rotation,
|
||||
// so flip the source bounds to match the same orientation.
|
||||
sourceBounds = new Rect(0, 0, sourceBounds.height(), sourceBounds.width());
|
||||
}
|
||||
final PipAnimationController.PipTransitionAnimator animator =
|
||||
mPipAnimationController.getAnimator(pipTaskInfo, leash, sourceBounds, sourceBounds,
|
||||
destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP,
|
||||
0 /* startingAngle */, 0 /* rotationDelta */)
|
||||
.setPipTransactionHandler(mTransactionConsumer)
|
||||
.setTransitionDirection(TRANSITION_DIRECTION_TO_PIP);
|
||||
// The start state is the end state for swipe-auto-pip.
|
||||
startTransaction.merge(finishTransaction);
|
||||
animator.applySurfaceControlTransaction(leash, startTransaction,
|
||||
PipAnimationController.FRACTION_END);
|
||||
startTransaction.apply();
|
||||
|
||||
mPipBoundsState.setBounds(destinationBounds);
|
||||
final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
|
||||
onFinishResize(pipTaskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, tx);
|
||||
sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
|
||||
if (swipePipToHomeOverlay != null) {
|
||||
mPipOrganizer.fadeOutAndRemoveOverlay(swipePipToHomeOverlay,
|
||||
null /* callback */, false /* withStartDelay */);
|
||||
}
|
||||
mPipTransitionState.setInSwipePipToHomeTransition(false);
|
||||
}
|
||||
|
||||
private void startExitToSplitAnimation(@NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction startTransaction,
|
||||
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||
|
||||
Reference in New Issue
Block a user