Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +9 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import com.android.wm.shell.desktopmode.DesktopPipTransitionController; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler; import com.android.wm.shell.pip2.PipSurfaceTransactionHelper; import com.android.wm.shell.pip2.phone.PhonePipMenuController; import com.android.wm.shell.pip2.phone.PipController; import com.android.wm.shell.pip2.phone.PipInteractionHandler; Loading Loading @@ -133,6 +134,7 @@ public abstract class Pip2Module { PipAppOpsListener pipAppOpsListener, PhonePipMenuController pipMenuController, PipUiEventLogger pipUiEventLogger, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, @ShellMainThread ShellExecutor mainExecutor) { if (!PipUtils.isPip2ExperimentEnabled()) { return Optional.empty(); Loading @@ -142,7 +144,7 @@ public abstract class Pip2Module { displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, pipTouchHandler, pipAppOpsListener, pipMenuController, pipUiEventLogger, mainExecutor)); pipUiEventLogger, pipSurfaceTransactionHelper, mainExecutor)); } } Loading Loading @@ -288,4 +290,10 @@ public abstract class Pip2Module { return new PipInteractionHandler(context, mainHandler, InteractionJankMonitor.getInstance()); } @WMSingleton @Provides static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context) { return new PipSurfaceTransactionHelper(context); } } libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java +67 −7 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.Debug; import android.util.Log; import android.view.SurfaceControl; import android.window.DesktopExperienceFlags; Loading Loading @@ -66,6 +65,7 @@ import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.common.pip.PipUiEventLogger; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip2.PipSurfaceTransactionHelper; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.sysui.ConfigurationChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; Loading @@ -87,6 +87,8 @@ public class PipController implements ConfigurationChangeListener, private static final String TAG = PipController.class.getSimpleName(); private static final String SWIPE_TO_PIP_APP_BOUNDS = "pip_app_bounds"; private static final String SWIPE_TO_PIP_OVERLAY = "swipe_to_pip_overlay"; private static final String DISPLAY_CHANGE_PIP_BOUNDS_UPDATE = "display_change_pip_bounds_update"; private final Context mContext; private final ShellCommandHandler mShellCommandHandler; Loading @@ -111,6 +113,10 @@ public class PipController implements ConfigurationChangeListener, // Wrapper for making Binder calls into PiP animation listener hosted in launcher's Recents. @Nullable private PipAnimationListener mPipRecentsAnimationListener; private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper; private boolean mWaitingToPlayDisplayChangeBoundsUpdate; @VisibleForTesting interface PipAnimationListener { /** Loading Loading @@ -150,6 +156,7 @@ public class PipController implements ConfigurationChangeListener, PipAppOpsListener pipAppOpsListener, PhonePipMenuController pipMenuController, PipUiEventLogger pipUiEventLogger, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, ShellExecutor mainExecutor) { mContext = context; mShellCommandHandler = shellCommandHandler; Loading @@ -168,6 +175,7 @@ public class PipController implements ConfigurationChangeListener, mPipAppOpsListener = pipAppOpsListener; mPipMenuController = pipMenuController; mPipUiEventLogger = pipUiEventLogger; mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper; mMainExecutor = mainExecutor; mImpl = new PipImpl(); Loading Loading @@ -196,6 +204,7 @@ public class PipController implements ConfigurationChangeListener, PipAppOpsListener pipAppOpsListener, PhonePipMenuController pipMenuController, PipUiEventLogger pipUiEventLogger, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, Loading @@ -206,7 +215,7 @@ public class PipController implements ConfigurationChangeListener, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, pipTouchHandler, pipAppOpsListener, pipMenuController, pipUiEventLogger, mainExecutor); pipUiEventLogger, pipSurfaceTransactionHelper, mainExecutor); } public PipImpl getPipImpl() { Loading Loading @@ -342,8 +351,7 @@ public class PipController implements ConfigurationChangeListener, mPipDisplayLayoutState.rotateTo(toRotation); } if (!mPipTransitionState.isInPip() && mPipTransitionState.getState() != PipTransitionState.ENTERING_PIP) { if (!shouldUpdatePipStateOnDisplayChange()) { // Skip the PiP-relevant updates if we aren't in a valid PiP state. if (mPipTransitionState.isInFixedRotation()) { ProtoLog.e(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, Loading Loading @@ -372,9 +380,13 @@ public class PipController implements ConfigurationChangeListener, mPipBoundsState.setBounds(toBounds); } if (mPipTransitionState.getPipTaskToken() == null) { Log.wtf(TAG, "PipController.onDisplayChange no PiP task token" + " state=" + mPipTransitionState.getState() + " callers=\n" + Debug.getCallers(4, " ")); Log.d(TAG, "PipController.onDisplayChange no PiP task token" + " state=" + mPipTransitionState.getState()); mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> { final Bundle extra = new Bundle(); extra.putBoolean(DISPLAY_CHANGE_PIP_BOUNDS_UPDATE, true); mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); }); } else { t.setBounds(mPipTransitionState.getPipTaskToken(), mPipBoundsState.getBounds()); } Loading @@ -386,6 +398,14 @@ public class PipController implements ConfigurationChangeListener, mPipDisplayLayoutState.setDisplayLayout(layout); } private boolean shouldUpdatePipStateOnDisplayChange() { // We should at least update internal PiP state, such as PiP bounds state or movement bounds // if we are either in PiP or about to enter PiP. return mPipTransitionState.isInPip() || mPipTransitionState.getState() == PipTransitionState.ENTERING_PIP || mPipTransitionState.getState() == PipTransitionState.SCHEDULED_ENTER_PIP; } // // IPip Binder stub helpers // Loading Loading @@ -510,7 +530,47 @@ public class PipController implements ConfigurationChangeListener, listener.accept(false /* inPip */); } break; case PipTransitionState.SCHEDULED_BOUNDS_CHANGE: mWaitingToPlayDisplayChangeBoundsUpdate = extra.getBoolean(DISPLAY_CHANGE_PIP_BOUNDS_UPDATE); if (mWaitingToPlayDisplayChangeBoundsUpdate) { // If we reach this point, it means display change did not send through a WCT to // update the pinned task bounds in Core. Instead, the local Shell-side // PiP-relevant bounds state and movement bounds were updated. // So schedule a jumpcut animation to those bounds now. mPipScheduler.scheduleAnimateResizePip(mPipBoundsState.getBounds()); } break; case PipTransitionState.CHANGING_PIP_BOUNDS: if (!mWaitingToPlayDisplayChangeBoundsUpdate) { break; } mWaitingToPlayDisplayChangeBoundsUpdate = false; final SurfaceControl.Transaction startTx = extra.getParcelable( PipTransition.PIP_START_TX, SurfaceControl.Transaction.class); final SurfaceControl.Transaction finishTx = extra.getParcelable( PipTransition.PIP_FINISH_TX, SurfaceControl.Transaction.class); final Rect destinationBounds = extra.getParcelable( PipTransition.PIP_DESTINATION_BOUNDS, Rect.class); handleJumpcutBoundsUpdate(startTx, finishTx, destinationBounds); break; } } private void handleJumpcutBoundsUpdate(SurfaceControl.Transaction startTx, SurfaceControl.Transaction finishTx, Rect destinationBounds) { SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); startTx.merge(finishTx); startTx.setPosition(pipLeash, destinationBounds.left, destinationBounds.top); mPipSurfaceTransactionHelper.round(startTx, pipLeash, true /* applyCornerRadius */) .shadow(startTx, pipLeash, true /* applyShadowRadius */); mPipSurfaceTransactionHelper.round(finishTx, pipLeash, true /* applyCornerRadius */) .shadow(finishTx, pipLeash, true /* applyShadowRadius */); startTx.apply(); // Signal that the transition is done - should update transition state by default. mPipScheduler.scheduleFinishPipBoundsChange(destinationBounds); } // Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +18 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.pip2.phone; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Surface.ROTATION_0; Loading Loading @@ -236,6 +237,7 @@ public class PipTransition extends PipTransitionController implements @NonNull TransitionRequestInfo request) { if (isAutoEnterInButtonNavigation(request) || isEnterPictureInPictureModeRequest(request)) { mEnterTransition = transition; mPipTransitionState.setState(PipTransitionState.SCHEDULED_ENTER_PIP); final WindowContainerTransaction wct = getEnterPipTransaction(transition, request.getPipChange()); Loading @@ -259,6 +261,7 @@ public class PipTransition extends PipTransitionController implements outWct.merge(getEnterPipTransaction(transition, request.getPipChange()), true /* transfer */); mEnterTransition = transition; mPipTransitionState.setState(PipTransitionState.SCHEDULED_ENTER_PIP); } } Loading Loading @@ -645,10 +648,22 @@ public class PipTransition extends PipTransitionController implements } mFinishCallback = finishCallback; Rect destinationBounds = pipChange.getEndAbsBounds(); SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); final Rect destinationBounds = pipChange.getEndAbsBounds(); if (pipChange.getEndRotation() != ROTATION_UNDEFINED && pipChange.getStartRotation() != pipChange.getEndRotation()) { // If we are playing an enter PiP animation with display change collected together // in the same transition, then PipController#onDisplayChange() must have already // updated the PiP bounds state to reflect the final desired destination bounds. // This might not be in the WM state yet as PiP task token might have been null then. // WM state will be updated via a follow-up bounds change transition after. destinationBounds.set(mPipBoundsState.getBounds()); } final SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); Preconditions.checkNotNull(pipLeash, "Leash is null for alpha transition."); // Note that fixed rotation is different from the same transition display change rotation; // with fixed rotation, we expect a follow-up async rotation transition after this one. final int delta = getFixedRotationDelta(info, pipChange, mPipDisplayLayoutState); if (delta != ROTATION_0) { updatePipChangesForFixedRotation(info, pipChange, Loading @@ -675,6 +690,7 @@ public class PipTransition extends PipTransitionController implements finishTransaction.setMatrix(pipLeash, transformTensor, matrixTmp); } else { startTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top); finishTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top); } PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipLeash, startTransaction, Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java +12 −7 Original line number Diff line number Diff line Loading @@ -76,27 +76,30 @@ public class PipTransitionState { // State for Launcher animating the swipe PiP to home animation. public static final int SWIPING_TO_PIP = 1; // State for scheduling enter PiP transition; could be after SWIPING_TO_PIP public static final int SCHEDULED_ENTER_PIP = 2; // State for Shell animating enter PiP or jump-cutting to PiP mode after Launcher animation. public static final int ENTERING_PIP = 2; public static final int ENTERING_PIP = 3; // State for app finishing drawing in PiP mode as a final step in enter PiP flow. public static final int ENTERED_PIP = 3; public static final int ENTERED_PIP = 4; // State to indicate we have scheduled a PiP bounds change transition. public static final int SCHEDULED_BOUNDS_CHANGE = 4; public static final int SCHEDULED_BOUNDS_CHANGE = 5; // State for the start of playing a transition to change PiP bounds. At this point, WM Core // is aware of the new PiP bounds, but Shell might still be continuing animating. public static final int CHANGING_PIP_BOUNDS = 5; public static final int CHANGING_PIP_BOUNDS = 6; // State for finishing animating into new PiP bounds after resize is complete. public static final int CHANGED_PIP_BOUNDS = 6; public static final int CHANGED_PIP_BOUNDS = 7; // State for starting exiting PiP. public static final int EXITING_PIP = 7; public static final int EXITING_PIP = 8; // State for finishing exit PiP flow. public static final int EXITED_PIP = 8; public static final int EXITED_PIP = 9; private static final int FIRST_CUSTOM_STATE = 1000; Loading @@ -105,6 +108,7 @@ public class PipTransitionState { @IntDef(prefix = { "TRANSITION_STATE_" }, value = { UNDEFINED, SWIPING_TO_PIP, SCHEDULED_ENTER_PIP, ENTERING_PIP, ENTERED_PIP, SCHEDULED_BOUNDS_CHANGE, Loading Loading @@ -421,6 +425,7 @@ public class PipTransitionState { switch (state) { case UNDEFINED: return "undefined"; case SWIPING_TO_PIP: return "swiping_to_pip"; case SCHEDULED_ENTER_PIP: return "scheduled_enter_pip"; case ENTERING_PIP: return "entering-pip"; case ENTERED_PIP: return "entered-pip"; case SCHEDULED_BOUNDS_CHANGE: return "scheduled_bounds_change"; Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +9 −1 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import com.android.wm.shell.desktopmode.DesktopPipTransitionController; import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.desktopmode.DesktopUserRepositories; import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler; import com.android.wm.shell.pip2.PipSurfaceTransactionHelper; import com.android.wm.shell.pip2.phone.PhonePipMenuController; import com.android.wm.shell.pip2.phone.PipController; import com.android.wm.shell.pip2.phone.PipInteractionHandler; Loading Loading @@ -133,6 +134,7 @@ public abstract class Pip2Module { PipAppOpsListener pipAppOpsListener, PhonePipMenuController pipMenuController, PipUiEventLogger pipUiEventLogger, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, @ShellMainThread ShellExecutor mainExecutor) { if (!PipUtils.isPip2ExperimentEnabled()) { return Optional.empty(); Loading @@ -142,7 +144,7 @@ public abstract class Pip2Module { displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, pipTouchHandler, pipAppOpsListener, pipMenuController, pipUiEventLogger, mainExecutor)); pipUiEventLogger, pipSurfaceTransactionHelper, mainExecutor)); } } Loading Loading @@ -288,4 +290,10 @@ public abstract class Pip2Module { return new PipInteractionHandler(context, mainHandler, InteractionJankMonitor.getInstance()); } @WMSingleton @Provides static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context) { return new PipSurfaceTransactionHelper(context); } }
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java +67 −7 Original line number Diff line number Diff line Loading @@ -31,7 +31,6 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; import android.os.Debug; import android.util.Log; import android.view.SurfaceControl; import android.window.DesktopExperienceFlags; Loading Loading @@ -66,6 +65,7 @@ import com.android.wm.shell.common.pip.PipDisplayLayoutState; import com.android.wm.shell.common.pip.PipUiEventLogger; import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip2.PipSurfaceTransactionHelper; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.sysui.ConfigurationChangeListener; import com.android.wm.shell.sysui.ShellCommandHandler; Loading @@ -87,6 +87,8 @@ public class PipController implements ConfigurationChangeListener, private static final String TAG = PipController.class.getSimpleName(); private static final String SWIPE_TO_PIP_APP_BOUNDS = "pip_app_bounds"; private static final String SWIPE_TO_PIP_OVERLAY = "swipe_to_pip_overlay"; private static final String DISPLAY_CHANGE_PIP_BOUNDS_UPDATE = "display_change_pip_bounds_update"; private final Context mContext; private final ShellCommandHandler mShellCommandHandler; Loading @@ -111,6 +113,10 @@ public class PipController implements ConfigurationChangeListener, // Wrapper for making Binder calls into PiP animation listener hosted in launcher's Recents. @Nullable private PipAnimationListener mPipRecentsAnimationListener; private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper; private boolean mWaitingToPlayDisplayChangeBoundsUpdate; @VisibleForTesting interface PipAnimationListener { /** Loading Loading @@ -150,6 +156,7 @@ public class PipController implements ConfigurationChangeListener, PipAppOpsListener pipAppOpsListener, PhonePipMenuController pipMenuController, PipUiEventLogger pipUiEventLogger, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, ShellExecutor mainExecutor) { mContext = context; mShellCommandHandler = shellCommandHandler; Loading @@ -168,6 +175,7 @@ public class PipController implements ConfigurationChangeListener, mPipAppOpsListener = pipAppOpsListener; mPipMenuController = pipMenuController; mPipUiEventLogger = pipUiEventLogger; mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper; mMainExecutor = mainExecutor; mImpl = new PipImpl(); Loading Loading @@ -196,6 +204,7 @@ public class PipController implements ConfigurationChangeListener, PipAppOpsListener pipAppOpsListener, PhonePipMenuController pipMenuController, PipUiEventLogger pipUiEventLogger, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, Loading @@ -206,7 +215,7 @@ public class PipController implements ConfigurationChangeListener, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, pipTouchHandler, pipAppOpsListener, pipMenuController, pipUiEventLogger, mainExecutor); pipUiEventLogger, pipSurfaceTransactionHelper, mainExecutor); } public PipImpl getPipImpl() { Loading Loading @@ -342,8 +351,7 @@ public class PipController implements ConfigurationChangeListener, mPipDisplayLayoutState.rotateTo(toRotation); } if (!mPipTransitionState.isInPip() && mPipTransitionState.getState() != PipTransitionState.ENTERING_PIP) { if (!shouldUpdatePipStateOnDisplayChange()) { // Skip the PiP-relevant updates if we aren't in a valid PiP state. if (mPipTransitionState.isInFixedRotation()) { ProtoLog.e(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, Loading Loading @@ -372,9 +380,13 @@ public class PipController implements ConfigurationChangeListener, mPipBoundsState.setBounds(toBounds); } if (mPipTransitionState.getPipTaskToken() == null) { Log.wtf(TAG, "PipController.onDisplayChange no PiP task token" + " state=" + mPipTransitionState.getState() + " callers=\n" + Debug.getCallers(4, " ")); Log.d(TAG, "PipController.onDisplayChange no PiP task token" + " state=" + mPipTransitionState.getState()); mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> { final Bundle extra = new Bundle(); extra.putBoolean(DISPLAY_CHANGE_PIP_BOUNDS_UPDATE, true); mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); }); } else { t.setBounds(mPipTransitionState.getPipTaskToken(), mPipBoundsState.getBounds()); } Loading @@ -386,6 +398,14 @@ public class PipController implements ConfigurationChangeListener, mPipDisplayLayoutState.setDisplayLayout(layout); } private boolean shouldUpdatePipStateOnDisplayChange() { // We should at least update internal PiP state, such as PiP bounds state or movement bounds // if we are either in PiP or about to enter PiP. return mPipTransitionState.isInPip() || mPipTransitionState.getState() == PipTransitionState.ENTERING_PIP || mPipTransitionState.getState() == PipTransitionState.SCHEDULED_ENTER_PIP; } // // IPip Binder stub helpers // Loading Loading @@ -510,7 +530,47 @@ public class PipController implements ConfigurationChangeListener, listener.accept(false /* inPip */); } break; case PipTransitionState.SCHEDULED_BOUNDS_CHANGE: mWaitingToPlayDisplayChangeBoundsUpdate = extra.getBoolean(DISPLAY_CHANGE_PIP_BOUNDS_UPDATE); if (mWaitingToPlayDisplayChangeBoundsUpdate) { // If we reach this point, it means display change did not send through a WCT to // update the pinned task bounds in Core. Instead, the local Shell-side // PiP-relevant bounds state and movement bounds were updated. // So schedule a jumpcut animation to those bounds now. mPipScheduler.scheduleAnimateResizePip(mPipBoundsState.getBounds()); } break; case PipTransitionState.CHANGING_PIP_BOUNDS: if (!mWaitingToPlayDisplayChangeBoundsUpdate) { break; } mWaitingToPlayDisplayChangeBoundsUpdate = false; final SurfaceControl.Transaction startTx = extra.getParcelable( PipTransition.PIP_START_TX, SurfaceControl.Transaction.class); final SurfaceControl.Transaction finishTx = extra.getParcelable( PipTransition.PIP_FINISH_TX, SurfaceControl.Transaction.class); final Rect destinationBounds = extra.getParcelable( PipTransition.PIP_DESTINATION_BOUNDS, Rect.class); handleJumpcutBoundsUpdate(startTx, finishTx, destinationBounds); break; } } private void handleJumpcutBoundsUpdate(SurfaceControl.Transaction startTx, SurfaceControl.Transaction finishTx, Rect destinationBounds) { SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); startTx.merge(finishTx); startTx.setPosition(pipLeash, destinationBounds.left, destinationBounds.top); mPipSurfaceTransactionHelper.round(startTx, pipLeash, true /* applyCornerRadius */) .shadow(startTx, pipLeash, true /* applyShadowRadius */); mPipSurfaceTransactionHelper.round(finishTx, pipLeash, true /* applyCornerRadius */) .shadow(finishTx, pipLeash, true /* applyShadowRadius */); startTx.apply(); // Signal that the transition is done - should update transition state by default. mPipScheduler.scheduleFinishPipBoundsChange(destinationBounds); } // Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +18 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.wm.shell.pip2.phone; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Surface.ROTATION_0; Loading Loading @@ -236,6 +237,7 @@ public class PipTransition extends PipTransitionController implements @NonNull TransitionRequestInfo request) { if (isAutoEnterInButtonNavigation(request) || isEnterPictureInPictureModeRequest(request)) { mEnterTransition = transition; mPipTransitionState.setState(PipTransitionState.SCHEDULED_ENTER_PIP); final WindowContainerTransaction wct = getEnterPipTransaction(transition, request.getPipChange()); Loading @@ -259,6 +261,7 @@ public class PipTransition extends PipTransitionController implements outWct.merge(getEnterPipTransaction(transition, request.getPipChange()), true /* transfer */); mEnterTransition = transition; mPipTransitionState.setState(PipTransitionState.SCHEDULED_ENTER_PIP); } } Loading Loading @@ -645,10 +648,22 @@ public class PipTransition extends PipTransitionController implements } mFinishCallback = finishCallback; Rect destinationBounds = pipChange.getEndAbsBounds(); SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); final Rect destinationBounds = pipChange.getEndAbsBounds(); if (pipChange.getEndRotation() != ROTATION_UNDEFINED && pipChange.getStartRotation() != pipChange.getEndRotation()) { // If we are playing an enter PiP animation with display change collected together // in the same transition, then PipController#onDisplayChange() must have already // updated the PiP bounds state to reflect the final desired destination bounds. // This might not be in the WM state yet as PiP task token might have been null then. // WM state will be updated via a follow-up bounds change transition after. destinationBounds.set(mPipBoundsState.getBounds()); } final SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash(); Preconditions.checkNotNull(pipLeash, "Leash is null for alpha transition."); // Note that fixed rotation is different from the same transition display change rotation; // with fixed rotation, we expect a follow-up async rotation transition after this one. final int delta = getFixedRotationDelta(info, pipChange, mPipDisplayLayoutState); if (delta != ROTATION_0) { updatePipChangesForFixedRotation(info, pipChange, Loading @@ -675,6 +690,7 @@ public class PipTransition extends PipTransitionController implements finishTransaction.setMatrix(pipLeash, transformTensor, matrixTmp); } else { startTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top); finishTransaction.setPosition(pipLeash, destinationBounds.left, destinationBounds.top); } PipAlphaAnimator animator = new PipAlphaAnimator(mContext, pipLeash, startTransaction, Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransitionState.java +12 −7 Original line number Diff line number Diff line Loading @@ -76,27 +76,30 @@ public class PipTransitionState { // State for Launcher animating the swipe PiP to home animation. public static final int SWIPING_TO_PIP = 1; // State for scheduling enter PiP transition; could be after SWIPING_TO_PIP public static final int SCHEDULED_ENTER_PIP = 2; // State for Shell animating enter PiP or jump-cutting to PiP mode after Launcher animation. public static final int ENTERING_PIP = 2; public static final int ENTERING_PIP = 3; // State for app finishing drawing in PiP mode as a final step in enter PiP flow. public static final int ENTERED_PIP = 3; public static final int ENTERED_PIP = 4; // State to indicate we have scheduled a PiP bounds change transition. public static final int SCHEDULED_BOUNDS_CHANGE = 4; public static final int SCHEDULED_BOUNDS_CHANGE = 5; // State for the start of playing a transition to change PiP bounds. At this point, WM Core // is aware of the new PiP bounds, but Shell might still be continuing animating. public static final int CHANGING_PIP_BOUNDS = 5; public static final int CHANGING_PIP_BOUNDS = 6; // State for finishing animating into new PiP bounds after resize is complete. public static final int CHANGED_PIP_BOUNDS = 6; public static final int CHANGED_PIP_BOUNDS = 7; // State for starting exiting PiP. public static final int EXITING_PIP = 7; public static final int EXITING_PIP = 8; // State for finishing exit PiP flow. public static final int EXITED_PIP = 8; public static final int EXITED_PIP = 9; private static final int FIRST_CUSTOM_STATE = 1000; Loading @@ -105,6 +108,7 @@ public class PipTransitionState { @IntDef(prefix = { "TRANSITION_STATE_" }, value = { UNDEFINED, SWIPING_TO_PIP, SCHEDULED_ENTER_PIP, ENTERING_PIP, ENTERED_PIP, SCHEDULED_BOUNDS_CHANGE, Loading Loading @@ -421,6 +425,7 @@ public class PipTransitionState { switch (state) { case UNDEFINED: return "undefined"; case SWIPING_TO_PIP: return "swiping_to_pip"; case SCHEDULED_ENTER_PIP: return "scheduled_enter_pip"; case ENTERING_PIP: return "entering-pip"; case ENTERED_PIP: return "entered-pip"; case SCHEDULED_BOUNDS_CHANGE: return "scheduled_bounds_change"; Loading