Loading core/java/android/window/WindowContainerTransaction.java +2 −2 Original line number Diff line number Diff line Loading @@ -109,8 +109,8 @@ public final class WindowContainerTransaction implements Parcelable { } /** * Notify activities within the hierarchy of a container that they have entered picture-in-picture * mode with the given bounds. * Notify {@link com.android.server.wm.PinnedTaskController} that the picture-in-picture task * has finished the enter animation with the given bounds. */ @NonNull public WindowContainerTransaction scheduleFinishEnterPip( Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +48 −29 Original line number Diff line number Diff line Loading @@ -427,36 +427,44 @@ public class PipAnimationController { Rect baseValue, Rect startValue, Rect endValue, Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction, float startingAngle, @Surface.Rotation int rotationDelta) { final boolean isOutPipDirection = isOutPipDirection(direction); // Just for simplicity we'll interpolate between the source rect hint insets and empty // insets to calculate the window crop final Rect initialSourceValue; if (isOutPipDirection(direction)) { if (isOutPipDirection) { initialSourceValue = new Rect(endValue); } else { initialSourceValue = new Rect(baseValue); } final Rect sourceHintRectInsets; if (sourceHintRect == null) { sourceHintRectInsets = null; } else { sourceHintRectInsets = new Rect(sourceHintRect.left - initialSourceValue.left, sourceHintRect.top - initialSourceValue.top, initialSourceValue.right - sourceHintRect.right, initialSourceValue.bottom - sourceHintRect.bottom); } final Rect sourceInsets = new Rect(0, 0, 0, 0); final Rect rotatedEndRect; final Rect lastEndRect; final Rect initialContainerRect; if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { lastEndRect = new Rect(endValue); rotatedEndRect = new Rect(endValue); // Rotate the end bounds according to the rotation delta because the display will // be rotated to the same orientation. rotatedEndRect = new Rect(endValue); rotateBounds(rotatedEndRect, endValue, rotationDelta); rotateBounds(rotatedEndRect, initialSourceValue, rotationDelta); // Use the rect that has the same orientation as the hint rect. initialContainerRect = isOutPipDirection ? rotatedEndRect : initialSourceValue; } else { rotatedEndRect = null; rotatedEndRect = lastEndRect = null; initialContainerRect = initialSourceValue; } final Rect sourceHintRectInsets; if (sourceHintRect == null) { sourceHintRectInsets = null; } else { sourceHintRectInsets = new Rect(sourceHintRect.left - initialContainerRect.left, sourceHintRect.top - initialContainerRect.top, initialContainerRect.right - sourceHintRect.right, initialContainerRect.bottom - sourceHintRect.bottom); } final Rect zeroInsets = new Rect(0, 0, 0, 0); // construct new Rect instances in case they are recycled return new PipTransitionAnimator<Rect>(taskInfo, leash, ANIM_TYPE_BOUNDS, endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue), Loading @@ -472,8 +480,8 @@ public class PipAnimationController { final Rect end = getEndValue(); if (rotatedEndRect != null) { // Animate the bounds in a different orientation. It only happens when // leaving PiP to fullscreen. applyRotation(tx, leash, fraction, start, end, rotatedEndRect); // switching between PiP and fullscreen. applyRotation(tx, leash, fraction, start, end); return; } Rect bounds = mRectEvaluator.evaluate(fraction, start, end); Loading @@ -481,20 +489,13 @@ public class PipAnimationController { setCurrentValue(bounds); if (inScaleTransition() || sourceHintRect == null) { if (isOutPipDirection(direction)) { if (isOutPipDirection) { getSurfaceTransactionHelper().scale(tx, leash, end, bounds); } else { getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle); } } else { final Rect insets; if (isOutPipDirection(direction)) { insets = mInsetsEvaluator.evaluate(fraction, sourceHintRectInsets, sourceInsets); } else { insets = mInsetsEvaluator.evaluate(fraction, sourceInsets, sourceHintRectInsets); } final Rect insets = computeInsets(fraction); getSurfaceTransactionHelper().scaleAndCrop(tx, leash, initialSourceValue, bounds, insets); } Loading @@ -502,9 +503,17 @@ public class PipAnimationController { } private void applyRotation(SurfaceControl.Transaction tx, SurfaceControl leash, float fraction, Rect start, Rect end, Rect rotatedEndRect) { float fraction, Rect start, Rect end) { if (!end.equals(lastEndRect)) { // If the end bounds are changed during animating (e.g. shelf height), the // rotated end bounds also need to be updated. rotatedEndRect.set(endValue); rotateBounds(rotatedEndRect, initialSourceValue, rotationDelta); lastEndRect.set(end); } final Rect bounds = mRectEvaluator.evaluate(fraction, start, rotatedEndRect); setCurrentValue(bounds); final Rect insets = computeInsets(fraction); final float degree, x, y; if (rotationDelta == ROTATION_90) { degree = 90 * fraction; Loading @@ -515,11 +524,21 @@ public class PipAnimationController { x = fraction * (end.left - start.left) + start.left; y = fraction * (end.bottom - start.top) + start.top; } getSurfaceTransactionHelper().rotateAndScaleWithCrop(tx, leash, bounds, rotatedEndRect, degree, x, y); getSurfaceTransactionHelper().rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection, rotationDelta == ROTATION_270 /* clockwise */); tx.apply(); } private Rect computeInsets(float fraction) { if (sourceHintRectInsets == null) { return zeroInsets; } final Rect startRect = isOutPipDirection ? sourceHintRectInsets : zeroInsets; final Rect endRect = isOutPipDirection ? zeroInsets : sourceHintRectInsets; return mInsetsEvaluator.evaluate(fraction, startRect, endRect); } @Override void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) { getSurfaceTransactionHelper() Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java +30 −12 Original line number Diff line number Diff line Loading @@ -137,23 +137,41 @@ public class PipSurfaceTransactionHelper { * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ public PipSurfaceTransactionHelper rotateAndScaleWithCrop(SurfaceControl.Transaction tx, SurfaceControl leash, Rect sourceBounds, Rect destinationBounds, float degrees, float positionX, float positionY) { SurfaceControl leash, Rect sourceBounds, Rect destinationBounds, Rect insets, float degrees, float positionX, float positionY, boolean isExpanding, boolean clockwise) { mTmpDestinationRect.set(sourceBounds); final int dw = destinationBounds.width(); final int dh = destinationBounds.height(); mTmpDestinationRect.inset(insets); final int srcW = mTmpDestinationRect.width(); final int srcH = mTmpDestinationRect.height(); final int destW = destinationBounds.width(); final int destH = destinationBounds.height(); // Scale by the short side so there won't be empty area if the aspect ratio of source and // destination are different. final float scale = dw <= dh ? (float) sourceBounds.width() / dw : (float) sourceBounds.height() / dh; final float scale = srcW <= srcH ? (float) destW / srcW : (float) destH / srcH; final Rect crop = mTmpDestinationRect; crop.set(0, 0, destW, destH); // Inverse scale for crop to fit in screen coordinates. mTmpDestinationRect.scale(1 / scale); mTmpTransform.setRotate(degrees); mTmpTransform.postScale(scale, scale); crop.scale(1 / scale); crop.offset(insets.left, insets.top); if (isExpanding) { // Expand bounds (shrink insets) in source orientation. positionX -= insets.left * scale; positionY -= insets.top * scale; } else { // Shrink bounds (expand insets) in destination orientation. if (clockwise) { positionX -= insets.top * scale; positionY -= insets.left * scale; } else { positionX += insets.top * scale; positionY += insets.left * scale; } } mTmpTransform.setScale(scale, scale); mTmpTransform.postRotate(degrees); mTmpTransform.postTranslate(positionX, positionY); tx.setMatrix(leash, mTmpTransform, mTmpFloat9) .setWindowCrop(leash, mTmpDestinationRect.width(), mTmpDestinationRect.height()); tx.setMatrix(leash, mTmpTransform, mTmpFloat9).setWindowCrop(leash, crop); return this; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +190 −43 File changed.Preview size limit exceeded, changes collapsed. Show changes libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +11 −7 Original line number Diff line number Diff line Loading @@ -114,13 +114,17 @@ public class PipController implements PipTransitionController.PipTransitionCallb */ private final DisplayChangeController.OnDisplayChangingListener mRotationController = ( int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> { if (!mPipTaskOrganizer.isInPip() || mPipBoundsState.getDisplayLayout().rotation() == toRotation || mPipTaskOrganizer.isDeferringEnterPipAnimation() || mPipTaskOrganizer.isEntryScheduled()) { // Skip if the same rotation has been set or 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. if (mPipBoundsState.getDisplayLayout().rotation() == toRotation) { // The same rotation may have been set by auto PiP-able or fixed rotation. So notify // the change with fromRotation=false to apply the rotated destination bounds from // PipTaskOrganizer#onMovementBoundsChanged. updateMovementBounds(null, false /* fromRotation */, false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t); return; } if (!mPipTaskOrganizer.isInPip() || mPipTaskOrganizer.isEntryScheduled()) { // Update display layout and bounds handler if we aren't in PIP or haven't actually // entered PIP yet. onDisplayRotationChangedNotInPip(mContext, toRotation); // do not forget to update the movement bounds as well. updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */, Loading Loading
core/java/android/window/WindowContainerTransaction.java +2 −2 Original line number Diff line number Diff line Loading @@ -109,8 +109,8 @@ public final class WindowContainerTransaction implements Parcelable { } /** * Notify activities within the hierarchy of a container that they have entered picture-in-picture * mode with the given bounds. * Notify {@link com.android.server.wm.PinnedTaskController} that the picture-in-picture task * has finished the enter animation with the given bounds. */ @NonNull public WindowContainerTransaction scheduleFinishEnterPip( Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +48 −29 Original line number Diff line number Diff line Loading @@ -427,36 +427,44 @@ public class PipAnimationController { Rect baseValue, Rect startValue, Rect endValue, Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction, float startingAngle, @Surface.Rotation int rotationDelta) { final boolean isOutPipDirection = isOutPipDirection(direction); // Just for simplicity we'll interpolate between the source rect hint insets and empty // insets to calculate the window crop final Rect initialSourceValue; if (isOutPipDirection(direction)) { if (isOutPipDirection) { initialSourceValue = new Rect(endValue); } else { initialSourceValue = new Rect(baseValue); } final Rect sourceHintRectInsets; if (sourceHintRect == null) { sourceHintRectInsets = null; } else { sourceHintRectInsets = new Rect(sourceHintRect.left - initialSourceValue.left, sourceHintRect.top - initialSourceValue.top, initialSourceValue.right - sourceHintRect.right, initialSourceValue.bottom - sourceHintRect.bottom); } final Rect sourceInsets = new Rect(0, 0, 0, 0); final Rect rotatedEndRect; final Rect lastEndRect; final Rect initialContainerRect; if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { lastEndRect = new Rect(endValue); rotatedEndRect = new Rect(endValue); // Rotate the end bounds according to the rotation delta because the display will // be rotated to the same orientation. rotatedEndRect = new Rect(endValue); rotateBounds(rotatedEndRect, endValue, rotationDelta); rotateBounds(rotatedEndRect, initialSourceValue, rotationDelta); // Use the rect that has the same orientation as the hint rect. initialContainerRect = isOutPipDirection ? rotatedEndRect : initialSourceValue; } else { rotatedEndRect = null; rotatedEndRect = lastEndRect = null; initialContainerRect = initialSourceValue; } final Rect sourceHintRectInsets; if (sourceHintRect == null) { sourceHintRectInsets = null; } else { sourceHintRectInsets = new Rect(sourceHintRect.left - initialContainerRect.left, sourceHintRect.top - initialContainerRect.top, initialContainerRect.right - sourceHintRect.right, initialContainerRect.bottom - sourceHintRect.bottom); } final Rect zeroInsets = new Rect(0, 0, 0, 0); // construct new Rect instances in case they are recycled return new PipTransitionAnimator<Rect>(taskInfo, leash, ANIM_TYPE_BOUNDS, endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue), Loading @@ -472,8 +480,8 @@ public class PipAnimationController { final Rect end = getEndValue(); if (rotatedEndRect != null) { // Animate the bounds in a different orientation. It only happens when // leaving PiP to fullscreen. applyRotation(tx, leash, fraction, start, end, rotatedEndRect); // switching between PiP and fullscreen. applyRotation(tx, leash, fraction, start, end); return; } Rect bounds = mRectEvaluator.evaluate(fraction, start, end); Loading @@ -481,20 +489,13 @@ public class PipAnimationController { setCurrentValue(bounds); if (inScaleTransition() || sourceHintRect == null) { if (isOutPipDirection(direction)) { if (isOutPipDirection) { getSurfaceTransactionHelper().scale(tx, leash, end, bounds); } else { getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle); } } else { final Rect insets; if (isOutPipDirection(direction)) { insets = mInsetsEvaluator.evaluate(fraction, sourceHintRectInsets, sourceInsets); } else { insets = mInsetsEvaluator.evaluate(fraction, sourceInsets, sourceHintRectInsets); } final Rect insets = computeInsets(fraction); getSurfaceTransactionHelper().scaleAndCrop(tx, leash, initialSourceValue, bounds, insets); } Loading @@ -502,9 +503,17 @@ public class PipAnimationController { } private void applyRotation(SurfaceControl.Transaction tx, SurfaceControl leash, float fraction, Rect start, Rect end, Rect rotatedEndRect) { float fraction, Rect start, Rect end) { if (!end.equals(lastEndRect)) { // If the end bounds are changed during animating (e.g. shelf height), the // rotated end bounds also need to be updated. rotatedEndRect.set(endValue); rotateBounds(rotatedEndRect, initialSourceValue, rotationDelta); lastEndRect.set(end); } final Rect bounds = mRectEvaluator.evaluate(fraction, start, rotatedEndRect); setCurrentValue(bounds); final Rect insets = computeInsets(fraction); final float degree, x, y; if (rotationDelta == ROTATION_90) { degree = 90 * fraction; Loading @@ -515,11 +524,21 @@ public class PipAnimationController { x = fraction * (end.left - start.left) + start.left; y = fraction * (end.bottom - start.top) + start.top; } getSurfaceTransactionHelper().rotateAndScaleWithCrop(tx, leash, bounds, rotatedEndRect, degree, x, y); getSurfaceTransactionHelper().rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection, rotationDelta == ROTATION_270 /* clockwise */); tx.apply(); } private Rect computeInsets(float fraction) { if (sourceHintRectInsets == null) { return zeroInsets; } final Rect startRect = isOutPipDirection ? sourceHintRectInsets : zeroInsets; final Rect endRect = isOutPipDirection ? zeroInsets : sourceHintRectInsets; return mInsetsEvaluator.evaluate(fraction, startRect, endRect); } @Override void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) { getSurfaceTransactionHelper() Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java +30 −12 Original line number Diff line number Diff line Loading @@ -137,23 +137,41 @@ public class PipSurfaceTransactionHelper { * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ public PipSurfaceTransactionHelper rotateAndScaleWithCrop(SurfaceControl.Transaction tx, SurfaceControl leash, Rect sourceBounds, Rect destinationBounds, float degrees, float positionX, float positionY) { SurfaceControl leash, Rect sourceBounds, Rect destinationBounds, Rect insets, float degrees, float positionX, float positionY, boolean isExpanding, boolean clockwise) { mTmpDestinationRect.set(sourceBounds); final int dw = destinationBounds.width(); final int dh = destinationBounds.height(); mTmpDestinationRect.inset(insets); final int srcW = mTmpDestinationRect.width(); final int srcH = mTmpDestinationRect.height(); final int destW = destinationBounds.width(); final int destH = destinationBounds.height(); // Scale by the short side so there won't be empty area if the aspect ratio of source and // destination are different. final float scale = dw <= dh ? (float) sourceBounds.width() / dw : (float) sourceBounds.height() / dh; final float scale = srcW <= srcH ? (float) destW / srcW : (float) destH / srcH; final Rect crop = mTmpDestinationRect; crop.set(0, 0, destW, destH); // Inverse scale for crop to fit in screen coordinates. mTmpDestinationRect.scale(1 / scale); mTmpTransform.setRotate(degrees); mTmpTransform.postScale(scale, scale); crop.scale(1 / scale); crop.offset(insets.left, insets.top); if (isExpanding) { // Expand bounds (shrink insets) in source orientation. positionX -= insets.left * scale; positionY -= insets.top * scale; } else { // Shrink bounds (expand insets) in destination orientation. if (clockwise) { positionX -= insets.top * scale; positionY -= insets.left * scale; } else { positionX += insets.top * scale; positionY += insets.left * scale; } } mTmpTransform.setScale(scale, scale); mTmpTransform.postRotate(degrees); mTmpTransform.postTranslate(positionX, positionY); tx.setMatrix(leash, mTmpTransform, mTmpFloat9) .setWindowCrop(leash, mTmpDestinationRect.width(), mTmpDestinationRect.height()); tx.setMatrix(leash, mTmpTransform, mTmpFloat9).setWindowCrop(leash, crop); return this; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +190 −43 File changed.Preview size limit exceeded, changes collapsed. Show changes
libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +11 −7 Original line number Diff line number Diff line Loading @@ -114,13 +114,17 @@ public class PipController implements PipTransitionController.PipTransitionCallb */ private final DisplayChangeController.OnDisplayChangingListener mRotationController = ( int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> { if (!mPipTaskOrganizer.isInPip() || mPipBoundsState.getDisplayLayout().rotation() == toRotation || mPipTaskOrganizer.isDeferringEnterPipAnimation() || mPipTaskOrganizer.isEntryScheduled()) { // Skip if the same rotation has been set or 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. if (mPipBoundsState.getDisplayLayout().rotation() == toRotation) { // The same rotation may have been set by auto PiP-able or fixed rotation. So notify // the change with fromRotation=false to apply the rotated destination bounds from // PipTaskOrganizer#onMovementBoundsChanged. updateMovementBounds(null, false /* fromRotation */, false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t); return; } if (!mPipTaskOrganizer.isInPip() || mPipTaskOrganizer.isEntryScheduled()) { // Update display layout and bounds handler if we aren't in PIP or haven't actually // entered PIP yet. onDisplayRotationChangedNotInPip(mContext, toRotation); // do not forget to update the movement bounds as well. updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */, Loading