Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +119 −55 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PIP; Loading Loading @@ -230,6 +231,11 @@ public class PipTransition extends PipTransitionController implements // If there is no PiP change, exit this transition handler and potentially try others. if (pipChange == null) return false; // Other targets might have default transforms applied that are not relevant when // playing PiP transitions, so reset those transforms if needed. prepareOtherTargetTransforms(info, startTransaction, finishTransaction); // Update the PipTransitionState while supplying the PiP leash and token to be cached. Bundle extra = new Bundle(); extra.putParcelable(PIP_TASK_TOKEN, pipChange.getContainer()); extra.putParcelable(PIP_TASK_LEASH, pipChange.getLeash()); Loading Loading @@ -341,17 +347,21 @@ public class PipTransition extends PipTransitionController implements (destinationBounds.height() - overlaySize) / 2f); } final int startRotation = pipChange.getStartRotation(); final int endRotation = mPipDisplayLayoutState.getRotation(); final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : startRotation - endRotation; final int delta = getFixedRotationDelta(info, pipChange); if (delta != ROTATION_0) { mPipTransitionState.setInFixedRotation(true); handleBoundsEnterFixedRotation(pipChange, pipActivityChange, endRotation); // Update transition target changes in place to prepare for fixed rotation. handleBoundsEnterFixedRotation(info, pipChange, pipActivityChange); } // Update the src-rect-hint in params in place, to set up initial animator transform. Rect sourceRectHint = getAdjustedSourceRectHint(info, pipChange, pipActivityChange); pipChange.getTaskInfo().pictureInPictureParams.getSourceRectHint().set(sourceRectHint); // Config-at-end transitions need to have their activities transformed before starting // the animation; this makes the buffer seem like it's been updated to final size. prepareConfigAtEndActivity(startTransaction, finishTransaction, pipChange, pipActivityChange); startTransaction.merge(finishTransaction); PipEnterAnimator animator = new PipEnterAnimator(mContext, pipLeash, startTransaction, finishTransaction, destinationBounds, delta); Loading Loading @@ -387,55 +397,36 @@ public class PipTransition extends PipTransitionController implements return false; } final SurfaceControl pipLeash = getLeash(pipChange); final Rect startBounds = pipChange.getStartAbsBounds(); final Rect endBounds = pipChange.getEndAbsBounds(); final PictureInPictureParams params = pipChange.getTaskInfo().pictureInPictureParams; final float aspectRatio = mPipBoundsAlgorithm.getAspectRatioOrDefault(params); final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, startBounds, endBounds); final Rect adjustedSourceRectHint = sourceRectHint != null ? new Rect(sourceRectHint) : PipUtils.getEnterPipWithOverlaySrcRectHint(startBounds, aspectRatio); final SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); // For opening type transitions, if there is a change of mode TO_FRONT/OPEN, // make sure that change has alpha of 1f, since it's init state might be set to alpha=0f // by the Transitions framework to simplify Task opening transitions. if (TransitionUtil.isOpeningType(info.getType())) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getLeash() == null) continue; if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) { startTransaction.setAlpha(change.getLeash(), 1f); } } } final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); final int startRotation = pipChange.getStartRotation(); final int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : ROTATION_UNDEFINED; final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : startRotation - endRotation; final Rect adjustedSourceRectHint = getAdjustedSourceRectHint(info, pipChange, pipActivityChange); final int delta = getFixedRotationDelta(info, pipChange); if (delta != ROTATION_0) { mPipTransitionState.setInFixedRotation(true); handleBoundsEnterFixedRotation(pipChange, pipActivityChange, fixedRotationChange.getEndFixedRotation()); // Update transition target changes in place to prepare for fixed rotation. handleBoundsEnterFixedRotation(info, pipChange, pipActivityChange); } PipEnterAnimator animator = new PipEnterAnimator(mContext, pipLeash, startTransaction, finishTransaction, endBounds, delta); if (sourceRectHint == null) { // update the src-rect-hint in params in place, to set up initial animator transform. params.getSourceRectHint().set(adjustedSourceRectHint); if (PipBoundsAlgorithm.getValidSourceHintRect(params, startBounds, endBounds) == null) { // If app provided src-rect-hint is invalid, use app icon overlay. animator.setAppIconContentOverlay( mContext, startBounds, endBounds, pipChange.getTaskInfo().topActivityInfo, mPipBoundsState.getLauncherState().getAppIconSizePx()); } // Update the src-rect-hint in params in place, to set up initial animator transform. params.getSourceRectHint().set(adjustedSourceRectHint); // Config-at-end transitions need to have their activities transformed before starting // the animation; this makes the buffer seem like it's been updated to final size. prepareConfigAtEndActivity(startTransaction, finishTransaction, pipChange, pipActivityChange); animator.setAnimationStartCallback(() -> animator.setEnterStartState(pipChange)); animator.setAnimationEndCallback(() -> { if (animator.getContentOverlayLeash() != null) { Loading @@ -457,11 +448,22 @@ public class PipTransition extends PipTransitionController implements animator.start(); } private void handleBoundsEnterFixedRotation(TransitionInfo.Change pipTaskChange, TransitionInfo.Change pipActivityChange, int endRotation) { final Rect endBounds = pipTaskChange.getEndAbsBounds(); final Rect endActivityBounds = pipActivityChange.getEndAbsBounds(); int startRotation = pipTaskChange.getStartRotation(); private void handleBoundsEnterFixedRotation(TransitionInfo info, TransitionInfo.Change outPipTaskChange, TransitionInfo.Change outPipActivityChange) { final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); final Rect endBounds = outPipTaskChange.getEndAbsBounds(); final Rect endActivityBounds = outPipActivityChange.getEndAbsBounds(); int startRotation = outPipTaskChange.getStartRotation(); int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : mPipDisplayLayoutState.getRotation(); if (startRotation == endRotation) { return; } // This is used by display change listeners to respond properly to fixed rotation. mPipTransitionState.setInFixedRotation(true); // Cache the task to activity offset to potentially restore later. Point activityEndOffset = new Point(endActivityBounds.left - endBounds.left, Loading Loading @@ -490,15 +492,15 @@ public class PipTransition extends PipTransitionController implements endBounds.top + activityEndOffset.y); } private void handleExpandFixedRotation(TransitionInfo.Change pipTaskChange, int endRotation) { final Rect endBounds = pipTaskChange.getEndAbsBounds(); private void handleExpandFixedRotation(TransitionInfo.Change outPipTaskChange, int delta) { final Rect endBounds = outPipTaskChange.getEndAbsBounds(); final int width = endBounds.width(); final int height = endBounds.height(); final int left = endBounds.left; final int top = endBounds.top; int newTop, newLeft; if (endRotation == Surface.ROTATION_90) { if (delta == Surface.ROTATION_90) { newLeft = top; newTop = -(left + width); } else { Loading Loading @@ -585,15 +587,11 @@ public class PipTransition extends PipTransitionController implements final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, endBounds, startBounds); final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); final int startRotation = pipChange.getStartRotation(); final int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : ROTATION_UNDEFINED; final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : endRotation - startRotation; // We define delta = startRotation - endRotation, so we need to flip the sign. final int delta = -getFixedRotationDelta(info, pipChange); if (delta != ROTATION_0) { handleExpandFixedRotation(pipChange, endRotation); // Update PiP target change in place to prepare for fixed rotation; handleExpandFixedRotation(pipChange, delta); } PipExpandAnimator animator = new PipExpandAnimator(mContext, pipLeash, Loading Loading @@ -661,6 +659,72 @@ public class PipTransition extends PipTransitionController implements return null; } @NonNull private Rect getAdjustedSourceRectHint(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change pipTaskChange, @NonNull TransitionInfo.Change pipActivityChange) { final Rect startBounds = pipTaskChange.getStartAbsBounds(); final Rect endBounds = pipTaskChange.getEndAbsBounds(); final PictureInPictureParams params = pipTaskChange.getTaskInfo().pictureInPictureParams; // Get the source-rect-hint provided by the app and check its validity; null if invalid. final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, startBounds, endBounds); final Rect adjustedSourceRectHint = new Rect(); if (sourceRectHint != null) { adjustedSourceRectHint.set(sourceRectHint); // If multi-activity PiP, use the parent task before PiP to retrieve display cutouts; // then, offset the valid app provided source rect hint by the cutout insets. // For single-activity PiP, just use the pinned task to get the cutouts instead. TransitionInfo.Change parentBeforePip = pipActivityChange.getLastParent() != null ? getChangeByToken(info, pipActivityChange.getLastParent()) : null; Rect cutoutInsets = parentBeforePip != null ? parentBeforePip.getTaskInfo().displayCutoutInsets : pipTaskChange.getTaskInfo().displayCutoutInsets; if (cutoutInsets != null && getFixedRotationDelta(info, pipTaskChange) == ROTATION_90) { adjustedSourceRectHint.offset(cutoutInsets.left, cutoutInsets.top); } } else { // For non-valid app provided src-rect-hint, calculate one to crop into during // app icon overlay animation. float aspectRatio = mPipBoundsAlgorithm.getAspectRatioOrDefault(params); adjustedSourceRectHint.set( PipUtils.getEnterPipWithOverlaySrcRectHint(startBounds, aspectRatio)); } return adjustedSourceRectHint; } @Surface.Rotation private int getFixedRotationDelta(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change pipChange) { TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); int startRotation = pipChange.getStartRotation(); int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : mPipDisplayLayoutState.getRotation(); int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : startRotation - endRotation; return delta; } private void prepareOtherTargetTransforms(TransitionInfo info, SurfaceControl.Transaction startTransaction, SurfaceControl.Transaction finishTransaction) { // For opening type transitions, if there is a change of mode TO_FRONT/OPEN, // make sure that change has alpha of 1f, since it's init state might be set to alpha=0f // by the Transitions framework to simplify Task opening transitions. if (TransitionUtil.isOpeningType(info.getType())) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getLeash() == null) continue; if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) { startTransaction.setAlpha(change.getLeash(), 1f); } } } } private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { // cache the original task token to check for multi-activity case later Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +119 −55 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_PIP; Loading Loading @@ -230,6 +231,11 @@ public class PipTransition extends PipTransitionController implements // If there is no PiP change, exit this transition handler and potentially try others. if (pipChange == null) return false; // Other targets might have default transforms applied that are not relevant when // playing PiP transitions, so reset those transforms if needed. prepareOtherTargetTransforms(info, startTransaction, finishTransaction); // Update the PipTransitionState while supplying the PiP leash and token to be cached. Bundle extra = new Bundle(); extra.putParcelable(PIP_TASK_TOKEN, pipChange.getContainer()); extra.putParcelable(PIP_TASK_LEASH, pipChange.getLeash()); Loading Loading @@ -341,17 +347,21 @@ public class PipTransition extends PipTransitionController implements (destinationBounds.height() - overlaySize) / 2f); } final int startRotation = pipChange.getStartRotation(); final int endRotation = mPipDisplayLayoutState.getRotation(); final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : startRotation - endRotation; final int delta = getFixedRotationDelta(info, pipChange); if (delta != ROTATION_0) { mPipTransitionState.setInFixedRotation(true); handleBoundsEnterFixedRotation(pipChange, pipActivityChange, endRotation); // Update transition target changes in place to prepare for fixed rotation. handleBoundsEnterFixedRotation(info, pipChange, pipActivityChange); } // Update the src-rect-hint in params in place, to set up initial animator transform. Rect sourceRectHint = getAdjustedSourceRectHint(info, pipChange, pipActivityChange); pipChange.getTaskInfo().pictureInPictureParams.getSourceRectHint().set(sourceRectHint); // Config-at-end transitions need to have their activities transformed before starting // the animation; this makes the buffer seem like it's been updated to final size. prepareConfigAtEndActivity(startTransaction, finishTransaction, pipChange, pipActivityChange); startTransaction.merge(finishTransaction); PipEnterAnimator animator = new PipEnterAnimator(mContext, pipLeash, startTransaction, finishTransaction, destinationBounds, delta); Loading Loading @@ -387,55 +397,36 @@ public class PipTransition extends PipTransitionController implements return false; } final SurfaceControl pipLeash = getLeash(pipChange); final Rect startBounds = pipChange.getStartAbsBounds(); final Rect endBounds = pipChange.getEndAbsBounds(); final PictureInPictureParams params = pipChange.getTaskInfo().pictureInPictureParams; final float aspectRatio = mPipBoundsAlgorithm.getAspectRatioOrDefault(params); final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, startBounds, endBounds); final Rect adjustedSourceRectHint = sourceRectHint != null ? new Rect(sourceRectHint) : PipUtils.getEnterPipWithOverlaySrcRectHint(startBounds, aspectRatio); final SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); // For opening type transitions, if there is a change of mode TO_FRONT/OPEN, // make sure that change has alpha of 1f, since it's init state might be set to alpha=0f // by the Transitions framework to simplify Task opening transitions. if (TransitionUtil.isOpeningType(info.getType())) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getLeash() == null) continue; if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) { startTransaction.setAlpha(change.getLeash(), 1f); } } } final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); final int startRotation = pipChange.getStartRotation(); final int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : ROTATION_UNDEFINED; final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : startRotation - endRotation; final Rect adjustedSourceRectHint = getAdjustedSourceRectHint(info, pipChange, pipActivityChange); final int delta = getFixedRotationDelta(info, pipChange); if (delta != ROTATION_0) { mPipTransitionState.setInFixedRotation(true); handleBoundsEnterFixedRotation(pipChange, pipActivityChange, fixedRotationChange.getEndFixedRotation()); // Update transition target changes in place to prepare for fixed rotation. handleBoundsEnterFixedRotation(info, pipChange, pipActivityChange); } PipEnterAnimator animator = new PipEnterAnimator(mContext, pipLeash, startTransaction, finishTransaction, endBounds, delta); if (sourceRectHint == null) { // update the src-rect-hint in params in place, to set up initial animator transform. params.getSourceRectHint().set(adjustedSourceRectHint); if (PipBoundsAlgorithm.getValidSourceHintRect(params, startBounds, endBounds) == null) { // If app provided src-rect-hint is invalid, use app icon overlay. animator.setAppIconContentOverlay( mContext, startBounds, endBounds, pipChange.getTaskInfo().topActivityInfo, mPipBoundsState.getLauncherState().getAppIconSizePx()); } // Update the src-rect-hint in params in place, to set up initial animator transform. params.getSourceRectHint().set(adjustedSourceRectHint); // Config-at-end transitions need to have their activities transformed before starting // the animation; this makes the buffer seem like it's been updated to final size. prepareConfigAtEndActivity(startTransaction, finishTransaction, pipChange, pipActivityChange); animator.setAnimationStartCallback(() -> animator.setEnterStartState(pipChange)); animator.setAnimationEndCallback(() -> { if (animator.getContentOverlayLeash() != null) { Loading @@ -457,11 +448,22 @@ public class PipTransition extends PipTransitionController implements animator.start(); } private void handleBoundsEnterFixedRotation(TransitionInfo.Change pipTaskChange, TransitionInfo.Change pipActivityChange, int endRotation) { final Rect endBounds = pipTaskChange.getEndAbsBounds(); final Rect endActivityBounds = pipActivityChange.getEndAbsBounds(); int startRotation = pipTaskChange.getStartRotation(); private void handleBoundsEnterFixedRotation(TransitionInfo info, TransitionInfo.Change outPipTaskChange, TransitionInfo.Change outPipActivityChange) { final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); final Rect endBounds = outPipTaskChange.getEndAbsBounds(); final Rect endActivityBounds = outPipActivityChange.getEndAbsBounds(); int startRotation = outPipTaskChange.getStartRotation(); int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : mPipDisplayLayoutState.getRotation(); if (startRotation == endRotation) { return; } // This is used by display change listeners to respond properly to fixed rotation. mPipTransitionState.setInFixedRotation(true); // Cache the task to activity offset to potentially restore later. Point activityEndOffset = new Point(endActivityBounds.left - endBounds.left, Loading Loading @@ -490,15 +492,15 @@ public class PipTransition extends PipTransitionController implements endBounds.top + activityEndOffset.y); } private void handleExpandFixedRotation(TransitionInfo.Change pipTaskChange, int endRotation) { final Rect endBounds = pipTaskChange.getEndAbsBounds(); private void handleExpandFixedRotation(TransitionInfo.Change outPipTaskChange, int delta) { final Rect endBounds = outPipTaskChange.getEndAbsBounds(); final int width = endBounds.width(); final int height = endBounds.height(); final int left = endBounds.left; final int top = endBounds.top; int newTop, newLeft; if (endRotation == Surface.ROTATION_90) { if (delta == Surface.ROTATION_90) { newLeft = top; newTop = -(left + width); } else { Loading Loading @@ -585,15 +587,11 @@ public class PipTransition extends PipTransitionController implements final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, endBounds, startBounds); final TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); final int startRotation = pipChange.getStartRotation(); final int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : ROTATION_UNDEFINED; final int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : endRotation - startRotation; // We define delta = startRotation - endRotation, so we need to flip the sign. final int delta = -getFixedRotationDelta(info, pipChange); if (delta != ROTATION_0) { handleExpandFixedRotation(pipChange, endRotation); // Update PiP target change in place to prepare for fixed rotation; handleExpandFixedRotation(pipChange, delta); } PipExpandAnimator animator = new PipExpandAnimator(mContext, pipLeash, Loading Loading @@ -661,6 +659,72 @@ public class PipTransition extends PipTransitionController implements return null; } @NonNull private Rect getAdjustedSourceRectHint(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change pipTaskChange, @NonNull TransitionInfo.Change pipActivityChange) { final Rect startBounds = pipTaskChange.getStartAbsBounds(); final Rect endBounds = pipTaskChange.getEndAbsBounds(); final PictureInPictureParams params = pipTaskChange.getTaskInfo().pictureInPictureParams; // Get the source-rect-hint provided by the app and check its validity; null if invalid. final Rect sourceRectHint = PipBoundsAlgorithm.getValidSourceHintRect(params, startBounds, endBounds); final Rect adjustedSourceRectHint = new Rect(); if (sourceRectHint != null) { adjustedSourceRectHint.set(sourceRectHint); // If multi-activity PiP, use the parent task before PiP to retrieve display cutouts; // then, offset the valid app provided source rect hint by the cutout insets. // For single-activity PiP, just use the pinned task to get the cutouts instead. TransitionInfo.Change parentBeforePip = pipActivityChange.getLastParent() != null ? getChangeByToken(info, pipActivityChange.getLastParent()) : null; Rect cutoutInsets = parentBeforePip != null ? parentBeforePip.getTaskInfo().displayCutoutInsets : pipTaskChange.getTaskInfo().displayCutoutInsets; if (cutoutInsets != null && getFixedRotationDelta(info, pipTaskChange) == ROTATION_90) { adjustedSourceRectHint.offset(cutoutInsets.left, cutoutInsets.top); } } else { // For non-valid app provided src-rect-hint, calculate one to crop into during // app icon overlay animation. float aspectRatio = mPipBoundsAlgorithm.getAspectRatioOrDefault(params); adjustedSourceRectHint.set( PipUtils.getEnterPipWithOverlaySrcRectHint(startBounds, aspectRatio)); } return adjustedSourceRectHint; } @Surface.Rotation private int getFixedRotationDelta(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change pipChange) { TransitionInfo.Change fixedRotationChange = findFixedRotationChange(info); int startRotation = pipChange.getStartRotation(); int endRotation = fixedRotationChange != null ? fixedRotationChange.getEndFixedRotation() : mPipDisplayLayoutState.getRotation(); int delta = endRotation == ROTATION_UNDEFINED ? ROTATION_0 : startRotation - endRotation; return delta; } private void prepareOtherTargetTransforms(TransitionInfo info, SurfaceControl.Transaction startTransaction, SurfaceControl.Transaction finishTransaction) { // For opening type transitions, if there is a change of mode TO_FRONT/OPEN, // make sure that change has alpha of 1f, since it's init state might be set to alpha=0f // by the Transitions framework to simplify Task opening transitions. if (TransitionUtil.isOpeningType(info.getType())) { for (TransitionInfo.Change change : info.getChanges()) { if (change.getLeash() == null) continue; if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) { startTransaction.setAlpha(change.getLeash(), 1f); } } } } private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition, @NonNull TransitionRequestInfo request) { // cache the original task token to check for multi-activity case later Loading