From 338bdd1f94d01c4d7514cb4d0adedbc0a57f1032 Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Fri, 25 Jun 2021 15:43:50 -0700 Subject: [PATCH] Polish auto-enter-pip from landscape and split-screen - Use Builder for constructing SwipePipToHomeAnimator since the parameter list grows - Use mHomeToWindowPositionMap to adjust the position, this is to fix the position issue when auto-enter-pip from split-screen - The position map and its inverse does not seem to fit the case when auto-enter-pip from landscape, leave it as it is - Setup the SwipePipToHomeAnimator the same way in createWindowAnimationToHome Video: http://recall/-/aaaaaabFQoRHlzixHdtY/b1j4eK7BU18sOGfuDlKMFR Bug: 190749305 Bug: 190855091 Test: manual, see video Change-Id: Ica9ca9f43b8fd5f1898fef4c6d173502dd897872 --- .../android/quickstep/AbsSwipeUpHandler.java | 44 +++-- .../util/SwipePipToHomeAnimator.java | 153 ++++++++++++++---- 2 files changed, 150 insertions(+), 47 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 4d47ef15c1..8da2aaad16 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -60,6 +60,7 @@ import android.content.Intent; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.Rect; +import android.graphics.RectF; import android.os.Build; import android.os.IBinder; import android.os.SystemClock; @@ -1217,30 +1218,40 @@ public abstract class AbsSwipeUpHandler, final RecentsOrientedState orientationState = mTaskViewSimulator.getOrientationState(); final int windowRotation = orientationState.getDisplayRotation(); final int homeRotation = orientationState.getRecentsActivityRotation(); + + final Matrix homeToWindowPositionMap = new Matrix(); + final RectF startRect = updateProgressForStartRect(homeToWindowPositionMap, startProgress); + // Move the startRect to Launcher space as floatingIconView runs in Launcher + final Matrix windowToHomePositionMap = new Matrix(); + homeToWindowPositionMap.invert(windowToHomePositionMap); + windowToHomePositionMap.mapRect(startRect); + final Rect destinationBounds = SystemUiProxy.INSTANCE.get(mContext) .startSwipePipToHome(taskInfo.topActivity, TaskInfoCompat.getTopActivityInfo(taskInfo), runningTaskTarget.taskInfo.pictureInPictureParams, homeRotation, mDp.hotseatBarSizePx); - final SwipePipToHomeAnimator swipePipToHomeAnimator = new SwipePipToHomeAnimator( - mContext, - runningTaskTarget.taskId, - taskInfo.topActivity, - runningTaskTarget.leash.getSurfaceControl(), - TaskInfoCompat.getPipSourceRectHint( - runningTaskTarget.taskInfo.pictureInPictureParams), - TaskInfoCompat.getWindowConfigurationBounds(taskInfo), - updateProgressForStartRect(new Matrix(), startProgress), - destinationBounds, - mRecentsView.getPipCornerRadius(), - mRecentsView); + final SwipePipToHomeAnimator.Builder builder = new SwipePipToHomeAnimator.Builder() + .setContext(mContext) + .setTaskId(runningTaskTarget.taskId) + .setComponentName(taskInfo.topActivity) + .setLeash(runningTaskTarget.leash.getSurfaceControl()) + .setSourceRectHint(TaskInfoCompat.getPipSourceRectHint( + runningTaskTarget.taskInfo.pictureInPictureParams)) + .setAppBounds(TaskInfoCompat.getWindowConfigurationBounds(taskInfo)) + .setHomeToWindowPositionMap(homeToWindowPositionMap) + .setStartBounds(startRect) + .setDestinationBounds(destinationBounds) + .setCornerRadius(mRecentsView.getPipCornerRadius()) + .setAttachedView(mRecentsView); // We would assume home and app window always in the same rotation While homeRotation // is not ROTATION_0 (which implies the rotation is turned on in launcher settings). if (homeRotation == ROTATION_0 && (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) { - swipePipToHomeAnimator.setFromRotation(mTaskViewSimulator, windowRotation); + builder.setFromRotation(mTaskViewSimulator, windowRotation); } + final SwipePipToHomeAnimator swipePipToHomeAnimator = builder.build(); AnimatorPlaybackController activityAnimationToHome = homeAnimFactory.createActivityAnimationToHome(); swipePipToHomeAnimator.addAnimatorListener(new AnimatorListenerAdapter() { @@ -1267,6 +1278,7 @@ public abstract class AbsSwipeUpHandler, mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED); } }); + setupWindowAnimation(swipePipToHomeAnimator); return swipePipToHomeAnimator; } @@ -1297,6 +1309,11 @@ public abstract class AbsSwipeUpHandler, HomeAnimationFactory homeAnimationFactory) { RectFSpringAnim anim = super.createWindowAnimationToHome(startProgress, homeAnimationFactory); + setupWindowAnimation(anim); + return anim; + } + + private void setupWindowAnimation(RectFSpringAnim anim) { anim.addOnUpdateListener((v, r, p) -> { updateSysUiFlags(Math.max(p, mCurrentShift.value)); }); @@ -1314,7 +1331,6 @@ public abstract class AbsSwipeUpHandler, if (mRecentsAnimationTargets != null) { mRecentsAnimationTargets.addReleaseCheck(anim); } - return anim; } public void onConsumerAboutToBeSwitched() { diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java index 67a635b70b..7488649eb7 100644 --- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java +++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java @@ -56,7 +56,9 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { private final ComponentName mComponentName; private final SurfaceControl mLeash; private final Rect mAppBounds = new Rect(); + private final Matrix mHomeToWindowPositionMap = new Matrix(); private final Rect mStartBounds = new Rect(); + private final RectF mCurrentBoundsF = new RectF(); private final Rect mCurrentBounds = new Rect(); private final Rect mDestinationBounds = new Rect(); private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; @@ -66,10 +68,9 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { private final Rect mSourceHintRectInsets; private final Rect mSourceInsets = new Rect(); - /** for rotation via {@link #setFromRotation(TaskViewSimulator, int)} */ - private @RecentsOrientedState.SurfaceRotation int mFromRotation = Surface.ROTATION_0; + /** for rotation calculations */ + private final @RecentsOrientedState.SurfaceRotation int mFromRotation; private final Rect mDestinationBoundsTransformed = new Rect(); - private final Rect mDestinationBoundsAnimation = new Rect(); /** * Flag to avoid the double-end problem since the leash would have been released @@ -91,31 +92,39 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { * @param leash {@link SurfaceControl} this animator operates on * @param sourceRectHint See the definition in {@link android.app.PictureInPictureParams} * @param appBounds Bounds of the application, sourceRectHint is based on this bounds + * @param homeToWindowPositionMap {@link Matrix} to map a Rect from home to window space * @param startBounds Bounds of the application when this animator starts. This can be * different from the appBounds if user has swiped a certain distance and * Launcher has performed transform on the leash. * @param destinationBounds Bounds of the destination this animator ends to + * @param fromRotation From rotation if different from final rotation, ROTATION_0 otherwise + * @param destinationBoundsTransformed Destination bounds in window space * @param cornerRadius Corner radius in pixel value for PiP window + * @param view Attached view for logging purpose */ - public SwipePipToHomeAnimator(@NonNull Context context, + private SwipePipToHomeAnimator(@NonNull Context context, int taskId, @NonNull ComponentName componentName, @NonNull SurfaceControl leash, @Nullable Rect sourceRectHint, @NonNull Rect appBounds, + @NonNull Matrix homeToWindowPositionMap, @NonNull RectF startBounds, @NonNull Rect destinationBounds, + @RecentsOrientedState.SurfaceRotation int fromRotation, + @NonNull Rect destinationBoundsTransformed, int cornerRadius, @NonNull View view) { - super(startBounds, new RectF(destinationBounds), context); + super(startBounds, new RectF(destinationBoundsTransformed), context); mTaskId = taskId; mComponentName = componentName; mLeash = leash; mAppBounds.set(appBounds); + mHomeToWindowPositionMap.set(homeToWindowPositionMap); startBounds.round(mStartBounds); mDestinationBounds.set(destinationBounds); - mDestinationBoundsTransformed.set(mDestinationBounds); - mDestinationBoundsAnimation.set(mDestinationBounds); + mFromRotation = fromRotation; + mDestinationBoundsTransformed.set(destinationBoundsTransformed); mSurfaceTransactionHelper = new PipSurfaceTransactionHelper(cornerRadius); if (sourceRectHint != null && (sourceRectHint.width() < destinationBounds.width() @@ -191,37 +200,13 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { addOnUpdateListener(this::onAnimationUpdate); } - /** sets the from rotation if it's different from the target rotation. */ - public void setFromRotation(TaskViewSimulator taskViewSimulator, - @RecentsOrientedState.SurfaceRotation int fromRotation) { - if (fromRotation != Surface.ROTATION_90 && fromRotation != Surface.ROTATION_270) { - Log.wtf(TAG, "Not a supported rotation, rotation=" + fromRotation); - return; - } - mFromRotation = fromRotation; - final Matrix matrix = new Matrix(); - taskViewSimulator.applyWindowToHomeRotation(matrix); - - // map the destination bounds into window space. mDestinationBounds is always calculated - // in the final home space and the animation runs in original window space. - final RectF transformed = new RectF(mDestinationBounds); - matrix.mapRect(transformed, new RectF(mDestinationBounds)); - transformed.round(mDestinationBoundsTransformed); - - // set the animation destination bounds for RectEvaluator calculation. - // bounds and insets are calculated as if the transition is from mAppBounds to - // mDestinationBoundsAnimation, separated from rotate / scale / position. - mDestinationBoundsAnimation.set(mAppBounds.left, mAppBounds.top, - mAppBounds.left + mDestinationBounds.width(), - mAppBounds.top + mDestinationBounds.height()); - } - private void onAnimationUpdate(@Nullable AppCloseConfig values, RectF currentRect, float progress) { if (mHasAnimationEnded) return; final SurfaceControl.Transaction tx = PipSurfaceTransactionHelper.newSurfaceControlTransaction(); - onAnimationUpdate(tx, currentRect, progress); + mHomeToWindowPositionMap.mapRect(mCurrentBoundsF, currentRect); + onAnimationUpdate(tx, mCurrentBoundsF, progress); tx.apply(); } @@ -309,6 +294,108 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim { return new RotatedPosition(degree, positionX, positionY); } + /** Builder class for {@link SwipePipToHomeAnimator} */ + public static class Builder { + private Context mContext; + private int mTaskId; + private ComponentName mComponentName; + private SurfaceControl mLeash; + private Rect mSourceRectHint; + private Rect mAppBounds; + private Matrix mHomeToWindowPositionMap; + private RectF mStartBounds; + private Rect mDestinationBounds; + private int mCornerRadius; + private View mAttachedView; + private @RecentsOrientedState.SurfaceRotation int mFromRotation = Surface.ROTATION_0; + private final Rect mDestinationBoundsTransformed = new Rect(); + + public Builder setContext(Context context) { + mContext = context; + return this; + } + + public Builder setTaskId(int taskId) { + mTaskId = taskId; + return this; + } + + public Builder setComponentName(ComponentName componentName) { + mComponentName = componentName; + return this; + } + + public Builder setLeash(SurfaceControl leash) { + mLeash = leash; + return this; + } + + public Builder setSourceRectHint(Rect sourceRectHint) { + mSourceRectHint = new Rect(sourceRectHint); + return this; + } + + public Builder setAppBounds(Rect appBounds) { + mAppBounds = new Rect(appBounds); + return this; + } + + public Builder setHomeToWindowPositionMap(Matrix homeToWindowPositionMap) { + mHomeToWindowPositionMap = new Matrix(homeToWindowPositionMap); + return this; + } + + public Builder setStartBounds(RectF startBounds) { + mStartBounds = new RectF(startBounds); + return this; + } + + public Builder setDestinationBounds(Rect destinationBounds) { + mDestinationBounds = new Rect(destinationBounds); + return this; + } + + public Builder setCornerRadius(int cornerRadius) { + mCornerRadius = cornerRadius; + return this; + } + + public Builder setAttachedView(View attachedView) { + mAttachedView = attachedView; + return this; + } + + public Builder setFromRotation(TaskViewSimulator taskViewSimulator, + @RecentsOrientedState.SurfaceRotation int fromRotation) { + if (fromRotation != Surface.ROTATION_90 && fromRotation != Surface.ROTATION_270) { + Log.wtf(TAG, "Not a supported rotation, rotation=" + fromRotation); + return this; + } + final Matrix matrix = new Matrix(); + taskViewSimulator.applyWindowToHomeRotation(matrix); + + // map the destination bounds into window space. mDestinationBounds is always calculated + // in the final home space and the animation runs in original window space. + final RectF transformed = new RectF(mDestinationBounds); + matrix.mapRect(transformed, new RectF(mDestinationBounds)); + transformed.round(mDestinationBoundsTransformed); + + mFromRotation = fromRotation; + return this; + } + + public SwipePipToHomeAnimator build() { + if (mDestinationBoundsTransformed.isEmpty()) { + mDestinationBoundsTransformed.set(mDestinationBounds); + } + return new SwipePipToHomeAnimator(mContext, mTaskId, mComponentName, mLeash, + mSourceRectHint, mAppBounds, + mHomeToWindowPositionMap, mStartBounds, mDestinationBounds, + mFromRotation, mDestinationBoundsTransformed, + mCornerRadius, mAttachedView); + } + } + private static class RotatedPosition { private final float degree; private final float positionX;