Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java +18 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,24 @@ public class PipBoundsAlgorithm { return adjustedNormalBounds; } /** * Snaps PiP bounds to its movement bounds. */ public void snapToMovementBoundsEdge(Rect bounds) { // Get the current movement bounds final Rect movementBounds = getMovementBounds(bounds); final int leftEdge = bounds.left; final int fromLeft = Math.abs(leftEdge - movementBounds.left); final int fromRight = Math.abs(movementBounds.right - leftEdge); // The PIP will be snapped to either the right or left edge, so calculate which one // is closest to the current position. final int newLeft = fromLeft < fromRight ? movementBounds.left : movementBounds.right; bounds.offsetTo(newLeft, bounds.top); } /** * Dumps internal states. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +4 −2 Original line number Diff line number Diff line Loading @@ -226,10 +226,12 @@ public abstract class Pip2Module { static PipDisplayTransferHandler providePipDisplayTransferHandler(Context context, PipTransitionState pipTransitionState, PipScheduler pipScheduler, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, PipBoundsState pipBoundsState, DisplayController displayController PipBoundsState pipBoundsState, DisplayController displayController, PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm ) { return new PipDisplayTransferHandler(context, pipTransitionState, pipScheduler, rootTaskDisplayAreaOrganizer, pipBoundsState, displayController); rootTaskDisplayAreaOrganizer, pipBoundsState, displayController, pipDisplayLayoutState, pipBoundsAlgorithm); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +3 −24 Original line number Diff line number Diff line Loading @@ -537,21 +537,8 @@ public class PipResizeGestureHandler { } } private void snapToMovementBoundsEdge(Rect bounds, Rect movementBounds) { final int leftEdge = bounds.left; final int fromLeft = Math.abs(leftEdge - movementBounds.left); final int fromRight = Math.abs(movementBounds.right - leftEdge); // The PIP will be snapped to either the right or left edge, so calculate which one // is closest to the current position. final int newLeft = fromLeft < fromRight ? movementBounds.left : movementBounds.right; bounds.offsetTo(newLeft, mLastResizeBounds.top); } /** * Resizes the pip window and updates user-resized bounds. * Loading @@ -561,11 +548,8 @@ public class PipResizeGestureHandler { void userResizeTo(Rect bounds, float snapFraction) { Rect finalBounds = new Rect(bounds); // get the current movement bounds final Rect movementBounds = mPipBoundsAlgorithm.getMovementBounds(finalBounds); // snap the target bounds to the either left or right edge, by choosing the closer one snapToMovementBoundsEdge(finalBounds, movementBounds); mPipBoundsAlgorithm.snapToMovementBoundsEdge(bounds); // apply the requested snap fraction onto the target bounds mPipBoundsAlgorithm.applySnapFraction(finalBounds, snapFraction); Loading Loading @@ -597,15 +581,10 @@ public class PipResizeGestureHandler { resizeRectAboutCenter(mLastResizeBounds, mMinSize.x, mMinSize.y); } // get the current movement bounds final Rect movementBounds = mPipBoundsAlgorithm .getMovementBounds(mLastResizeBounds); // snap mLastResizeBounds to the correct edge based on movement bounds snapToMovementBoundsEdge(mLastResizeBounds, movementBounds); mPipBoundsAlgorithm.snapToMovementBoundsEdge(mLastResizeBounds); final float snapFraction = mPipBoundsAlgorithm.getSnapFraction( mLastResizeBounds, movementBounds); final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mLastResizeBounds); mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction); // disable any touch events beyond resizing too Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandler.java +101 −17 Original line number Diff line number Diff line Loading @@ -15,7 +15,11 @@ */ package com.android.wm.shell.pip2.phone; import static com.android.wm.shell.pip2.phone.PipTransition.ANIMATING_BOUNDS_CHANGE_DURATION; import static com.android.wm.shell.pip2.phone.PipTransition.PIP_DESTINATION_BOUNDS; import android.annotation.Nullable; import android.app.TaskInfo; import android.content.Context; import android.graphics.Rect; import android.graphics.RectF; Loading @@ -27,12 +31,17 @@ import android.view.SurfaceControl.Transaction; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.MultiDisplayDragMoveBoundsCalculator; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.pip2.PipSurfaceTransactionHelper; import com.android.wm.shell.pip2.animation.PipResizeAnimator; import com.android.wm.shell.protolog.ShellProtoLogGroup; /** * Handler for moving PiP window to another display when the device is connected to external Loading @@ -53,14 +62,21 @@ public class PipDisplayTransferHandler implements private final DisplayController mDisplayController; private final PipTransitionState mPipTransitionState; private final PipScheduler mPipScheduler; private final Context mContext; private final PipDisplayLayoutState mPipDisplayLayoutState; private final PipBoundsAlgorithm mPipBoundsAlgorithm; @VisibleForTesting boolean mWaitingForDisplayTransfer; @VisibleForTesting ArrayMap<Integer, SurfaceControl> mOnDragMirrorPerDisplayId = new ArrayMap<>(); private int mTargetDisplayId; private PipResizeAnimatorSupplier mPipResizeAnimatorSupplier; public PipDisplayTransferHandler(Context context, PipTransitionState pipTransitionState, PipScheduler pipScheduler, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, PipBoundsState pipBoundsState, DisplayController displayController) { PipBoundsState pipBoundsState, DisplayController displayController, PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm) { mContext = context; mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); mPipScheduler = pipScheduler; Loading @@ -70,12 +86,20 @@ public class PipDisplayTransferHandler implements mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context); mPipBoundsState = pipBoundsState; mDisplayController = displayController; mPipDisplayLayoutState = pipDisplayLayoutState; mPipBoundsAlgorithm = pipBoundsAlgorithm; mPipResizeAnimatorSupplier = PipResizeAnimator::new; } void scheduleMovePipToDisplay(int originDisplayId, int targetDisplayId) { void scheduleMovePipToDisplay(int originDisplayId, int targetDisplayId, Rect destinationBounds) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s scheduleMovePipToDisplay from=%d to=%d", TAG, originDisplayId, targetDisplayId); Bundle extra = new Bundle(); extra.putInt(ORIGIN_DISPLAY_ID_KEY, originDisplayId); extra.putInt(TARGET_DISPLAY_ID_KEY, targetDisplayId); extra.putParcelable(PIP_DESTINATION_BOUNDS, destinationBounds); mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); } Loading @@ -83,36 +107,77 @@ public class PipDisplayTransferHandler implements @Override public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState, @PipTransitionState.TransitionState int newState, @Nullable Bundle extra) { if (extra == null) return; switch (newState) { case PipTransitionState.SCHEDULED_BOUNDS_CHANGE: if (extra == null || !extra.containsKey(ORIGIN_DISPLAY_ID_KEY) || !extra.containsKey(TARGET_DISPLAY_ID_KEY)) { if (!extra.containsKey(ORIGIN_DISPLAY_ID_KEY) || !extra.containsKey( TARGET_DISPLAY_ID_KEY)) { break; } final int originDisplayId = extra.getInt(ORIGIN_DISPLAY_ID_KEY); mTargetDisplayId = extra.getInt(TARGET_DISPLAY_ID_KEY); if (originDisplayId == mTargetDisplayId) { break; } mWaitingForDisplayTransfer = true; mPipScheduler.scheduleMoveToDisplay(extra.getInt(ORIGIN_DISPLAY_ID_KEY), extra.getInt(TARGET_DISPLAY_ID_KEY)); mWaitingForDisplayTransfer = true; mPipScheduler.scheduleMoveToDisplay(mTargetDisplayId, extra.getParcelable(PIP_DESTINATION_BOUNDS, Rect.class)); break; case PipTransitionState.CHANGING_PIP_BOUNDS: if (extra == null || !mWaitingForDisplayTransfer) { if (!mWaitingForDisplayTransfer) { break; } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s Animating PiP display change to=%d", TAG, mTargetDisplayId); SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); TaskInfo taskInfo = mPipTransitionState.getPipTaskInfo(); final int duration = extra.getInt(ANIMATING_BOUNDS_CHANGE_DURATION, PipTransition.BOUNDS_CHANGE_JUMPCUT_DURATION); final Transaction startTx = extra.getParcelable( PipTransition.PIP_START_TX, Transaction.class); final Rect destinationBounds = extra.getParcelable( PipTransition.PIP_DESTINATION_BOUNDS, Rect.class); final Transaction finishTx = extra.getParcelable( PipTransition.PIP_FINISH_TX, Transaction.class); final Rect pipBounds = extra.getParcelable( PIP_DESTINATION_BOUNDS, Rect.class); startMoveToDisplayAnimation(startTx, destinationBounds); } } Rect finalBounds = new Rect(pipBounds); mPipBoundsAlgorithm.snapToMovementBoundsEdge(finalBounds); private void startMoveToDisplayAnimation(Transaction startTx, Rect destinationBounds) { if (startTx == null) return; mPipSurfaceTransactionHelper.round(startTx, pipLeash, true).shadow(startTx, pipLeash, true /* applyShadowRadius */); // Set state to exiting and exited PiP to unregister input consumer on the current // display. // TODO(b/414864788): Refactor transition states setting during display transfer mPipTransitionState.setState(PipTransitionState.EXITING_PIP); mPipTransitionState.setState(PipTransitionState.EXITED_PIP); startTx.apply(); mPipScheduler.scheduleFinishPipBoundsChange(destinationBounds); mPipDisplayLayoutState.setDisplayId(mTargetDisplayId); mPipDisplayLayoutState.setDisplayLayout(mDisplayController.getDisplayLayout( mTargetDisplayId)); mPipTransitionState.setPinnedTaskLeash(pipLeash); mPipTransitionState.setPipTaskInfo(taskInfo); final PipResizeAnimator animator = mPipResizeAnimatorSupplier.get(mContext, mPipSurfaceTransactionHelper, pipLeash, startTx, finishTx, pipBounds, pipBounds, finalBounds, duration, 0); animator.setAnimationEndCallback(() -> { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s Finished animating PiP display change to=%d", TAG, mTargetDisplayId); mPipScheduler.scheduleFinishPipBoundsChange(finalBounds); // Set state to ENTERED_PIP to register input consumer on the target display mPipTransitionState.setState(PipTransitionState.ENTERED_PIP); mPipBoundsState.setHasUserResizedPip(true); mWaitingForDisplayTransfer = false; }); animator.start(); break; } } /** Loading Loading @@ -188,4 +253,23 @@ public class PipDisplayTransferHandler implements void setSurfaceTransactionHelper(PipSurfaceTransactionHelper surfaceTransactionHelper) { mPipSurfaceTransactionHelper = surfaceTransactionHelper; } @VisibleForTesting interface PipResizeAnimatorSupplier { PipResizeAnimator get(@NonNull Context context, @NonNull PipSurfaceTransactionHelper pipSurfaceTransactionHelper, @NonNull SurfaceControl leash, @Nullable SurfaceControl.Transaction startTx, @Nullable SurfaceControl.Transaction finishTx, @NonNull Rect baseBounds, @NonNull Rect startBounds, @NonNull Rect endBounds, int duration, float delta); } @VisibleForTesting void setPipResizeAnimatorSupplier(@NonNull PipResizeAnimatorSupplier supplier) { mPipResizeAnimatorSupplier = supplier; } } libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipInputConsumer.java +6 −1 Original line number Diff line number Diff line Loading @@ -140,6 +140,8 @@ public class PipInputConsumer { final InputChannel inputChannel = new InputChannel(); try { final int displayId = mPipDisplayLayoutState.getDisplayId(); ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Creating input consumer on displayID: %d", TAG, displayId); mWindowManager.destroyInputConsumer(mToken, displayId); mWindowManager.createInputConsumer(mToken, mName, displayId, inputChannel); } catch (RemoteException e) { Loading @@ -163,7 +165,10 @@ public class PipInputConsumer { return; } try { mWindowManager.destroyInputConsumer(mToken, mPipDisplayLayoutState.getDisplayId()); final int displayId = mPipDisplayLayoutState.getDisplayId(); ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Destroying input consumer on displayID: %d", TAG, displayId); mWindowManager.destroyInputConsumer(mToken, displayId); } catch (RemoteException e) { ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Failed to destroy input consumer, %s", TAG, e); Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsAlgorithm.java +18 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,24 @@ public class PipBoundsAlgorithm { return adjustedNormalBounds; } /** * Snaps PiP bounds to its movement bounds. */ public void snapToMovementBoundsEdge(Rect bounds) { // Get the current movement bounds final Rect movementBounds = getMovementBounds(bounds); final int leftEdge = bounds.left; final int fromLeft = Math.abs(leftEdge - movementBounds.left); final int fromRight = Math.abs(movementBounds.right - leftEdge); // The PIP will be snapped to either the right or left edge, so calculate which one // is closest to the current position. final int newLeft = fromLeft < fromRight ? movementBounds.left : movementBounds.right; bounds.offsetTo(newLeft, bounds.top); } /** * Dumps internal states. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +4 −2 Original line number Diff line number Diff line Loading @@ -226,10 +226,12 @@ public abstract class Pip2Module { static PipDisplayTransferHandler providePipDisplayTransferHandler(Context context, PipTransitionState pipTransitionState, PipScheduler pipScheduler, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, PipBoundsState pipBoundsState, DisplayController displayController PipBoundsState pipBoundsState, DisplayController displayController, PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm ) { return new PipDisplayTransferHandler(context, pipTransitionState, pipScheduler, rootTaskDisplayAreaOrganizer, pipBoundsState, displayController); rootTaskDisplayAreaOrganizer, pipBoundsState, displayController, pipDisplayLayoutState, pipBoundsAlgorithm); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +3 −24 Original line number Diff line number Diff line Loading @@ -537,21 +537,8 @@ public class PipResizeGestureHandler { } } private void snapToMovementBoundsEdge(Rect bounds, Rect movementBounds) { final int leftEdge = bounds.left; final int fromLeft = Math.abs(leftEdge - movementBounds.left); final int fromRight = Math.abs(movementBounds.right - leftEdge); // The PIP will be snapped to either the right or left edge, so calculate which one // is closest to the current position. final int newLeft = fromLeft < fromRight ? movementBounds.left : movementBounds.right; bounds.offsetTo(newLeft, mLastResizeBounds.top); } /** * Resizes the pip window and updates user-resized bounds. * Loading @@ -561,11 +548,8 @@ public class PipResizeGestureHandler { void userResizeTo(Rect bounds, float snapFraction) { Rect finalBounds = new Rect(bounds); // get the current movement bounds final Rect movementBounds = mPipBoundsAlgorithm.getMovementBounds(finalBounds); // snap the target bounds to the either left or right edge, by choosing the closer one snapToMovementBoundsEdge(finalBounds, movementBounds); mPipBoundsAlgorithm.snapToMovementBoundsEdge(bounds); // apply the requested snap fraction onto the target bounds mPipBoundsAlgorithm.applySnapFraction(finalBounds, snapFraction); Loading Loading @@ -597,15 +581,10 @@ public class PipResizeGestureHandler { resizeRectAboutCenter(mLastResizeBounds, mMinSize.x, mMinSize.y); } // get the current movement bounds final Rect movementBounds = mPipBoundsAlgorithm .getMovementBounds(mLastResizeBounds); // snap mLastResizeBounds to the correct edge based on movement bounds snapToMovementBoundsEdge(mLastResizeBounds, movementBounds); mPipBoundsAlgorithm.snapToMovementBoundsEdge(mLastResizeBounds); final float snapFraction = mPipBoundsAlgorithm.getSnapFraction( mLastResizeBounds, movementBounds); final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mLastResizeBounds); mPipBoundsAlgorithm.applySnapFraction(mLastResizeBounds, snapFraction); // disable any touch events beyond resizing too Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipDisplayTransferHandler.java +101 −17 Original line number Diff line number Diff line Loading @@ -15,7 +15,11 @@ */ package com.android.wm.shell.pip2.phone; import static com.android.wm.shell.pip2.phone.PipTransition.ANIMATING_BOUNDS_CHANGE_DURATION; import static com.android.wm.shell.pip2.phone.PipTransition.PIP_DESTINATION_BOUNDS; import android.annotation.Nullable; import android.app.TaskInfo; import android.content.Context; import android.graphics.Rect; import android.graphics.RectF; Loading @@ -27,12 +31,17 @@ import android.view.SurfaceControl.Transaction; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.internal.protolog.ProtoLog; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.MultiDisplayDragMoveBoundsCalculator; import com.android.wm.shell.common.pip.PipBoundsAlgorithm; import com.android.wm.shell.common.pip.PipBoundsState; import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.pip2.PipSurfaceTransactionHelper; import com.android.wm.shell.pip2.animation.PipResizeAnimator; import com.android.wm.shell.protolog.ShellProtoLogGroup; /** * Handler for moving PiP window to another display when the device is connected to external Loading @@ -53,14 +62,21 @@ public class PipDisplayTransferHandler implements private final DisplayController mDisplayController; private final PipTransitionState mPipTransitionState; private final PipScheduler mPipScheduler; private final Context mContext; private final PipDisplayLayoutState mPipDisplayLayoutState; private final PipBoundsAlgorithm mPipBoundsAlgorithm; @VisibleForTesting boolean mWaitingForDisplayTransfer; @VisibleForTesting ArrayMap<Integer, SurfaceControl> mOnDragMirrorPerDisplayId = new ArrayMap<>(); private int mTargetDisplayId; private PipResizeAnimatorSupplier mPipResizeAnimatorSupplier; public PipDisplayTransferHandler(Context context, PipTransitionState pipTransitionState, PipScheduler pipScheduler, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, PipBoundsState pipBoundsState, DisplayController displayController) { PipBoundsState pipBoundsState, DisplayController displayController, PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm) { mContext = context; mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); mPipScheduler = pipScheduler; Loading @@ -70,12 +86,20 @@ public class PipDisplayTransferHandler implements mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context); mPipBoundsState = pipBoundsState; mDisplayController = displayController; mPipDisplayLayoutState = pipDisplayLayoutState; mPipBoundsAlgorithm = pipBoundsAlgorithm; mPipResizeAnimatorSupplier = PipResizeAnimator::new; } void scheduleMovePipToDisplay(int originDisplayId, int targetDisplayId) { void scheduleMovePipToDisplay(int originDisplayId, int targetDisplayId, Rect destinationBounds) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s scheduleMovePipToDisplay from=%d to=%d", TAG, originDisplayId, targetDisplayId); Bundle extra = new Bundle(); extra.putInt(ORIGIN_DISPLAY_ID_KEY, originDisplayId); extra.putInt(TARGET_DISPLAY_ID_KEY, targetDisplayId); extra.putParcelable(PIP_DESTINATION_BOUNDS, destinationBounds); mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); } Loading @@ -83,36 +107,77 @@ public class PipDisplayTransferHandler implements @Override public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState, @PipTransitionState.TransitionState int newState, @Nullable Bundle extra) { if (extra == null) return; switch (newState) { case PipTransitionState.SCHEDULED_BOUNDS_CHANGE: if (extra == null || !extra.containsKey(ORIGIN_DISPLAY_ID_KEY) || !extra.containsKey(TARGET_DISPLAY_ID_KEY)) { if (!extra.containsKey(ORIGIN_DISPLAY_ID_KEY) || !extra.containsKey( TARGET_DISPLAY_ID_KEY)) { break; } final int originDisplayId = extra.getInt(ORIGIN_DISPLAY_ID_KEY); mTargetDisplayId = extra.getInt(TARGET_DISPLAY_ID_KEY); if (originDisplayId == mTargetDisplayId) { break; } mWaitingForDisplayTransfer = true; mPipScheduler.scheduleMoveToDisplay(extra.getInt(ORIGIN_DISPLAY_ID_KEY), extra.getInt(TARGET_DISPLAY_ID_KEY)); mWaitingForDisplayTransfer = true; mPipScheduler.scheduleMoveToDisplay(mTargetDisplayId, extra.getParcelable(PIP_DESTINATION_BOUNDS, Rect.class)); break; case PipTransitionState.CHANGING_PIP_BOUNDS: if (extra == null || !mWaitingForDisplayTransfer) { if (!mWaitingForDisplayTransfer) { break; } ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s Animating PiP display change to=%d", TAG, mTargetDisplayId); SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); TaskInfo taskInfo = mPipTransitionState.getPipTaskInfo(); final int duration = extra.getInt(ANIMATING_BOUNDS_CHANGE_DURATION, PipTransition.BOUNDS_CHANGE_JUMPCUT_DURATION); final Transaction startTx = extra.getParcelable( PipTransition.PIP_START_TX, Transaction.class); final Rect destinationBounds = extra.getParcelable( PipTransition.PIP_DESTINATION_BOUNDS, Rect.class); final Transaction finishTx = extra.getParcelable( PipTransition.PIP_FINISH_TX, Transaction.class); final Rect pipBounds = extra.getParcelable( PIP_DESTINATION_BOUNDS, Rect.class); startMoveToDisplayAnimation(startTx, destinationBounds); } } Rect finalBounds = new Rect(pipBounds); mPipBoundsAlgorithm.snapToMovementBoundsEdge(finalBounds); private void startMoveToDisplayAnimation(Transaction startTx, Rect destinationBounds) { if (startTx == null) return; mPipSurfaceTransactionHelper.round(startTx, pipLeash, true).shadow(startTx, pipLeash, true /* applyShadowRadius */); // Set state to exiting and exited PiP to unregister input consumer on the current // display. // TODO(b/414864788): Refactor transition states setting during display transfer mPipTransitionState.setState(PipTransitionState.EXITING_PIP); mPipTransitionState.setState(PipTransitionState.EXITED_PIP); startTx.apply(); mPipScheduler.scheduleFinishPipBoundsChange(destinationBounds); mPipDisplayLayoutState.setDisplayId(mTargetDisplayId); mPipDisplayLayoutState.setDisplayLayout(mDisplayController.getDisplayLayout( mTargetDisplayId)); mPipTransitionState.setPinnedTaskLeash(pipLeash); mPipTransitionState.setPipTaskInfo(taskInfo); final PipResizeAnimator animator = mPipResizeAnimatorSupplier.get(mContext, mPipSurfaceTransactionHelper, pipLeash, startTx, finishTx, pipBounds, pipBounds, finalBounds, duration, 0); animator.setAnimationEndCallback(() -> { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s Finished animating PiP display change to=%d", TAG, mTargetDisplayId); mPipScheduler.scheduleFinishPipBoundsChange(finalBounds); // Set state to ENTERED_PIP to register input consumer on the target display mPipTransitionState.setState(PipTransitionState.ENTERED_PIP); mPipBoundsState.setHasUserResizedPip(true); mWaitingForDisplayTransfer = false; }); animator.start(); break; } } /** Loading Loading @@ -188,4 +253,23 @@ public class PipDisplayTransferHandler implements void setSurfaceTransactionHelper(PipSurfaceTransactionHelper surfaceTransactionHelper) { mPipSurfaceTransactionHelper = surfaceTransactionHelper; } @VisibleForTesting interface PipResizeAnimatorSupplier { PipResizeAnimator get(@NonNull Context context, @NonNull PipSurfaceTransactionHelper pipSurfaceTransactionHelper, @NonNull SurfaceControl leash, @Nullable SurfaceControl.Transaction startTx, @Nullable SurfaceControl.Transaction finishTx, @NonNull Rect baseBounds, @NonNull Rect startBounds, @NonNull Rect endBounds, int duration, float delta); } @VisibleForTesting void setPipResizeAnimatorSupplier(@NonNull PipResizeAnimatorSupplier supplier) { mPipResizeAnimatorSupplier = supplier; } }
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipInputConsumer.java +6 −1 Original line number Diff line number Diff line Loading @@ -140,6 +140,8 @@ public class PipInputConsumer { final InputChannel inputChannel = new InputChannel(); try { final int displayId = mPipDisplayLayoutState.getDisplayId(); ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Creating input consumer on displayID: %d", TAG, displayId); mWindowManager.destroyInputConsumer(mToken, displayId); mWindowManager.createInputConsumer(mToken, mName, displayId, inputChannel); } catch (RemoteException e) { Loading @@ -163,7 +165,10 @@ public class PipInputConsumer { return; } try { mWindowManager.destroyInputConsumer(mToken, mPipDisplayLayoutState.getDisplayId()); final int displayId = mPipDisplayLayoutState.getDisplayId(); ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Destroying input consumer on displayID: %d", TAG, displayId); mWindowManager.destroyInputConsumer(mToken, displayId); } catch (RemoteException e) { ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: Failed to destroy input consumer, %s", TAG, e); Loading