Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +2 −1 Original line number Diff line number Diff line Loading @@ -104,6 +104,7 @@ public abstract class Pip2Module { TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, @ShellMainThread ShellExecutor mainExecutor) { if (!PipUtils.isPip2ExperimentEnabled()) { return Optional.empty(); Loading @@ -112,7 +113,7 @@ public abstract class Pip2Module { context, shellInit, shellCommandHandler, shellController, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, mainExecutor)); pipTransitionState, pipTouchHandler, mainExecutor)); } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java +8 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public class PipController implements ConfigurationChangeListener, private final TaskStackListenerImpl mTaskStackListener; private final ShellTaskOrganizer mShellTaskOrganizer; private final PipTransitionState mPipTransitionState; private final PipTouchHandler mPipTouchHandler; private final ShellExecutor mMainExecutor; private final PipImpl mImpl; private Consumer<Boolean> mOnIsInPipStateChangedListener; Loading Loading @@ -130,6 +131,7 @@ public class PipController implements ConfigurationChangeListener, TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, ShellExecutor mainExecutor) { mContext = context; mShellCommandHandler = shellCommandHandler; Loading @@ -144,6 +146,7 @@ public class PipController implements ConfigurationChangeListener, mShellTaskOrganizer = shellTaskOrganizer; mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); mPipTouchHandler = pipTouchHandler; mMainExecutor = mainExecutor; mImpl = new PipImpl(); Loading @@ -168,6 +171,7 @@ public class PipController implements ConfigurationChangeListener, TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, Loading @@ -177,7 +181,7 @@ public class PipController implements ConfigurationChangeListener, return new PipController(context, shellInit, shellCommandHandler, shellController, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, mainExecutor); pipTransitionState, pipTouchHandler, mainExecutor); } public PipImpl getPipImpl() { Loading @@ -204,7 +208,9 @@ public class PipController implements ConfigurationChangeListener, mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(), new ImeListener(mDisplayController, mPipDisplayLayoutState.getDisplayId()) { @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { mPipTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight); } }); // Allow other outside processes to bind to PiP controller using the key below. Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java +39 −11 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private final PhysicsAnimator.SpringConfig mConflictResolutionSpringConfig = new PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_NO_BOUNCY); @Nullable private Runnable mUpdateMovementBoundsRunnable; private final Consumer<Rect> mUpdateBoundsCallback = (Rect newBounds) -> { if (mPipBoundsState.getBounds().equals(newBounds)) { return; Loading @@ -141,6 +143,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mMenuController.updateMenuLayout(newBounds); mPipBoundsState.setBounds(newBounds); maybeUpdateMovementBounds(); }; /** Loading Loading @@ -566,11 +569,20 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, + " callers=\n%s", TAG, originalBounds, offset, Debug.getCallers(5, " ")); } if (offset == 0) { return; } cancelPhysicsAnimation(); /* mPipTaskOrganizer.scheduleOffsetPip(originalBounds, offset, SHIFT_DURATION, mUpdateBoundsCallback); */ Rect adjustedBounds = new Rect(originalBounds); adjustedBounds.offset(0, offset); setAnimatingToBounds(adjustedBounds); Bundle extra = new Bundle(); extra.putBoolean(ANIMATING_BOUNDS_CHANGE, true); extra.putInt(ANIMATING_BOUNDS_CHANGE_DURATION, SHIFT_DURATION); mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); } /** Loading @@ -585,11 +597,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, /** Set new fling configs whose min/max values respect the given movement bounds. */ private void rebuildFlingConfigs() { mFlingConfigX = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION, mPipBoundsAlgorithm.getMovementBounds(getBounds()).left, mPipBoundsAlgorithm.getMovementBounds(getBounds()).right); mPipBoundsState.getMovementBounds().left, mPipBoundsState.getMovementBounds().right); mFlingConfigY = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION, mPipBoundsAlgorithm.getMovementBounds(getBounds()).top, mPipBoundsAlgorithm.getMovementBounds(getBounds()).bottom); mPipBoundsState.getMovementBounds().top, mPipBoundsState.getMovementBounds().bottom); final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets(); mStashConfigX = new PhysicsAnimator.FlingConfig( DEFAULT_FRICTION, Loading Loading @@ -671,6 +683,16 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, cleanUpHighPerfSessionMaybe(); } void setUpdateMovementBoundsRunnable(Runnable updateMovementBoundsRunnable) { mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable; } private void maybeUpdateMovementBounds() { if (mUpdateMovementBoundsRunnable != null) { mUpdateMovementBoundsRunnable.run(); } } /** * Notifies the floating coordinator that we're moving, and sets the animating to bounds so * we return these bounds from Loading Loading @@ -807,8 +829,14 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, startTx, finishTx, mPipBoundsState.getBounds(), mPipBoundsState.getBounds(), destinationBounds, duration, 0f /* angle */); animator.setAnimationEndCallback(() -> { mPipBoundsState.setBounds(destinationBounds); // All motion operations have actually finished, so make bounds cache updates. mUpdateBoundsCallback.accept(destinationBounds); // In case an ongoing drag/fling was present before a deterministic resize transition // kicked in, we need to update the update bounds properly before cleaning in-motion // state. mPipBoundsState.getMotionBoundsState().setBoundsInMotion(destinationBounds); settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */); cleanUpHighPerfSessionMaybe(); // Signal that we are done with resize transition mPipScheduler.scheduleFinishResizePip(true /* configAtEnd */); Loading @@ -817,7 +845,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } private void settlePipBoundsAfterPhysicsAnimation(boolean animatingAfter) { if (!animatingAfter) { if (!animatingAfter && mPipBoundsState.getMotionBoundsState().isInMotion()) { // The physics animation ended, though we may not necessarily be done animating, such as // when we're still dragging after moving out of the magnetic target. Only set the final // bounds state and clear motion bounds completely if the whole animation is over. Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java +1 −1 Original line number Diff line number Diff line Loading @@ -146,8 +146,8 @@ public class PipResizeGestureHandler implements mUpdateResizeBoundsCallback = (rect) -> { mUserResizeBounds.set(rect); // mMotionHelper.synchronizePinnedStackBounds(); mUpdateMovementBoundsRunnable.run(); mPipBoundsState.setBounds(rect); mUpdateMovementBoundsRunnable.run(); resetState(); }; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java +20 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha mMenuController.addListener(new PipMenuListener()); mGesture = new DefaultPipTouchGesture(); mMotionHelper = pipMotionHelper; mMotionHelper.setUpdateMovementBoundsRunnable(this::updateMovementBounds); mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger, mMotionHelper, mainExecutor); mTouchState = new PipTouchState(ViewConfiguration.get(context), Loading Loading @@ -317,6 +318,8 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha mFloatingContentCoordinator.onContentRemoved(mMotionHelper); mPipResizeGestureHandler.onActivityUnpinned(); mPipInputConsumer.unregisterInputConsumer(); mPipBoundsState.setHasUserMovedPip(false); mPipBoundsState.setHasUserResizedPip(false); } void onPinnedStackAnimationEnded( Loading Loading @@ -346,6 +349,22 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { mIsImeShowing = imeVisible; mImeHeight = imeHeight; // Cache new movement bounds using the new potential IME height. updateMovementBounds(); mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> { int delta = mPipBoundsState.getMovementBounds().bottom - mPipBoundsState.getBounds().top; boolean hasUserInteracted = (mPipBoundsState.hasUserMovedPip() || mPipBoundsState.hasUserResizedPip()); if ((imeVisible && delta < 0) || (!imeVisible && !hasUserInteracted)) { // The policy is to ignore an IME disappearing if user has interacted with PiP. // Otherwise, only offset due to an appearing IME if PiP occludes it. mMotionHelper.animateToOffset(mPipBoundsState.getBounds(), delta); } }); } void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) { Loading Loading @@ -1077,6 +1096,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha switch (newState) { case PipTransitionState.ENTERED_PIP: onActivityPinned(); updateMovementBounds(); mTouchState.setAllowInputEvents(true); mTouchState.reset(); break; Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java +2 −1 Original line number Diff line number Diff line Loading @@ -104,6 +104,7 @@ public abstract class Pip2Module { TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, @ShellMainThread ShellExecutor mainExecutor) { if (!PipUtils.isPip2ExperimentEnabled()) { return Optional.empty(); Loading @@ -112,7 +113,7 @@ public abstract class Pip2Module { context, shellInit, shellCommandHandler, shellController, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, mainExecutor)); pipTransitionState, pipTouchHandler, mainExecutor)); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipController.java +8 −2 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public class PipController implements ConfigurationChangeListener, private final TaskStackListenerImpl mTaskStackListener; private final ShellTaskOrganizer mShellTaskOrganizer; private final PipTransitionState mPipTransitionState; private final PipTouchHandler mPipTouchHandler; private final ShellExecutor mMainExecutor; private final PipImpl mImpl; private Consumer<Boolean> mOnIsInPipStateChangedListener; Loading Loading @@ -130,6 +131,7 @@ public class PipController implements ConfigurationChangeListener, TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, ShellExecutor mainExecutor) { mContext = context; mShellCommandHandler = shellCommandHandler; Loading @@ -144,6 +146,7 @@ public class PipController implements ConfigurationChangeListener, mShellTaskOrganizer = shellTaskOrganizer; mPipTransitionState = pipTransitionState; mPipTransitionState.addPipTransitionStateChangedListener(this); mPipTouchHandler = pipTouchHandler; mMainExecutor = mainExecutor; mImpl = new PipImpl(); Loading @@ -168,6 +171,7 @@ public class PipController implements ConfigurationChangeListener, TaskStackListenerImpl taskStackListener, ShellTaskOrganizer shellTaskOrganizer, PipTransitionState pipTransitionState, PipTouchHandler pipTouchHandler, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, Loading @@ -177,7 +181,7 @@ public class PipController implements ConfigurationChangeListener, return new PipController(context, shellInit, shellCommandHandler, shellController, displayController, displayInsetsController, pipBoundsState, pipBoundsAlgorithm, pipDisplayLayoutState, pipScheduler, taskStackListener, shellTaskOrganizer, pipTransitionState, mainExecutor); pipTransitionState, pipTouchHandler, mainExecutor); } public PipImpl getPipImpl() { Loading @@ -204,7 +208,9 @@ public class PipController implements ConfigurationChangeListener, mDisplayInsetsController.addInsetsChangedListener(mPipDisplayLayoutState.getDisplayId(), new ImeListener(mDisplayController, mPipDisplayLayoutState.getDisplayId()) { @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { mPipTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight); } }); // Allow other outside processes to bind to PiP controller using the key below. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java +39 −11 Original line number Diff line number Diff line Loading @@ -134,6 +134,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private final PhysicsAnimator.SpringConfig mConflictResolutionSpringConfig = new PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_NO_BOUNCY); @Nullable private Runnable mUpdateMovementBoundsRunnable; private final Consumer<Rect> mUpdateBoundsCallback = (Rect newBounds) -> { if (mPipBoundsState.getBounds().equals(newBounds)) { return; Loading @@ -141,6 +143,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, mMenuController.updateMenuLayout(newBounds); mPipBoundsState.setBounds(newBounds); maybeUpdateMovementBounds(); }; /** Loading Loading @@ -566,11 +569,20 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, + " callers=\n%s", TAG, originalBounds, offset, Debug.getCallers(5, " ")); } if (offset == 0) { return; } cancelPhysicsAnimation(); /* mPipTaskOrganizer.scheduleOffsetPip(originalBounds, offset, SHIFT_DURATION, mUpdateBoundsCallback); */ Rect adjustedBounds = new Rect(originalBounds); adjustedBounds.offset(0, offset); setAnimatingToBounds(adjustedBounds); Bundle extra = new Bundle(); extra.putBoolean(ANIMATING_BOUNDS_CHANGE, true); extra.putInt(ANIMATING_BOUNDS_CHANGE_DURATION, SHIFT_DURATION); mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra); } /** Loading @@ -585,11 +597,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, /** Set new fling configs whose min/max values respect the given movement bounds. */ private void rebuildFlingConfigs() { mFlingConfigX = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION, mPipBoundsAlgorithm.getMovementBounds(getBounds()).left, mPipBoundsAlgorithm.getMovementBounds(getBounds()).right); mPipBoundsState.getMovementBounds().left, mPipBoundsState.getMovementBounds().right); mFlingConfigY = new PhysicsAnimator.FlingConfig(DEFAULT_FRICTION, mPipBoundsAlgorithm.getMovementBounds(getBounds()).top, mPipBoundsAlgorithm.getMovementBounds(getBounds()).bottom); mPipBoundsState.getMovementBounds().top, mPipBoundsState.getMovementBounds().bottom); final Rect insetBounds = mPipBoundsState.getDisplayLayout().stableInsets(); mStashConfigX = new PhysicsAnimator.FlingConfig( DEFAULT_FRICTION, Loading Loading @@ -671,6 +683,16 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, cleanUpHighPerfSessionMaybe(); } void setUpdateMovementBoundsRunnable(Runnable updateMovementBoundsRunnable) { mUpdateMovementBoundsRunnable = updateMovementBoundsRunnable; } private void maybeUpdateMovementBounds() { if (mUpdateMovementBoundsRunnable != null) { mUpdateMovementBoundsRunnable.run(); } } /** * Notifies the floating coordinator that we're moving, and sets the animating to bounds so * we return these bounds from Loading Loading @@ -807,8 +829,14 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, startTx, finishTx, mPipBoundsState.getBounds(), mPipBoundsState.getBounds(), destinationBounds, duration, 0f /* angle */); animator.setAnimationEndCallback(() -> { mPipBoundsState.setBounds(destinationBounds); // All motion operations have actually finished, so make bounds cache updates. mUpdateBoundsCallback.accept(destinationBounds); // In case an ongoing drag/fling was present before a deterministic resize transition // kicked in, we need to update the update bounds properly before cleaning in-motion // state. mPipBoundsState.getMotionBoundsState().setBoundsInMotion(destinationBounds); settlePipBoundsAfterPhysicsAnimation(false /* animatingAfter */); cleanUpHighPerfSessionMaybe(); // Signal that we are done with resize transition mPipScheduler.scheduleFinishResizePip(true /* configAtEnd */); Loading @@ -817,7 +845,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, } private void settlePipBoundsAfterPhysicsAnimation(boolean animatingAfter) { if (!animatingAfter) { if (!animatingAfter && mPipBoundsState.getMotionBoundsState().isInMotion()) { // The physics animation ended, though we may not necessarily be done animating, such as // when we're still dragging after moving out of the magnetic target. Only set the final // bounds state and clear motion bounds completely if the whole animation is over. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipResizeGestureHandler.java +1 −1 Original line number Diff line number Diff line Loading @@ -146,8 +146,8 @@ public class PipResizeGestureHandler implements mUpdateResizeBoundsCallback = (rect) -> { mUserResizeBounds.set(rect); // mMotionHelper.synchronizePinnedStackBounds(); mUpdateMovementBoundsRunnable.run(); mPipBoundsState.setBounds(rect); mUpdateMovementBoundsRunnable.run(); resetState(); }; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java +20 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha mMenuController.addListener(new PipMenuListener()); mGesture = new DefaultPipTouchGesture(); mMotionHelper = pipMotionHelper; mMotionHelper.setUpdateMovementBoundsRunnable(this::updateMovementBounds); mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger, mMotionHelper, mainExecutor); mTouchState = new PipTouchState(ViewConfiguration.get(context), Loading Loading @@ -317,6 +318,8 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha mFloatingContentCoordinator.onContentRemoved(mMotionHelper); mPipResizeGestureHandler.onActivityUnpinned(); mPipInputConsumer.unregisterInputConsumer(); mPipBoundsState.setHasUserMovedPip(false); mPipBoundsState.setHasUserResizedPip(false); } void onPinnedStackAnimationEnded( Loading Loading @@ -346,6 +349,22 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { mIsImeShowing = imeVisible; mImeHeight = imeHeight; // Cache new movement bounds using the new potential IME height. updateMovementBounds(); mPipTransitionState.setOnIdlePipTransitionStateRunnable(() -> { int delta = mPipBoundsState.getMovementBounds().bottom - mPipBoundsState.getBounds().top; boolean hasUserInteracted = (mPipBoundsState.hasUserMovedPip() || mPipBoundsState.hasUserResizedPip()); if ((imeVisible && delta < 0) || (!imeVisible && !hasUserInteracted)) { // The policy is to ignore an IME disappearing if user has interacted with PiP. // Otherwise, only offset due to an appearing IME if PiP occludes it. mMotionHelper.animateToOffset(mPipBoundsState.getBounds(), delta); } }); } void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) { Loading Loading @@ -1077,6 +1096,7 @@ public class PipTouchHandler implements PipTransitionState.PipTransitionStateCha switch (newState) { case PipTransitionState.ENTERED_PIP: onActivityPinned(); updateMovementBounds(); mTouchState.setAllowInputEvents(true); mTouchState.reset(); break; Loading