Loading core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +5 −0 Original line number Diff line number Diff line Loading @@ -394,6 +394,11 @@ public final class SystemUiDeviceConfigFlags { */ public static final String PIP_PINCH_RESIZE = "pip_pinch_resize"; /** * (boolean) Whether to enable stashing for PIP. */ public static final String PIP_STASHING = "pip_stashing"; /** * (float) Bottom height in DP for Back Gesture. */ Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +28 −3 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private static final int EXPAND_STACK_TO_MENU_DURATION = 250; private static final int LEAVE_PIP_DURATION = 300; private static final int SHIFT_DURATION = 300; private static final float STASH_RATIO = 0.25f; /** Friction to use for PIP when it moves via physics fling animations. */ private static final float DEFAULT_FRICTION = 2f; Loading Loading @@ -120,6 +121,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, /** FlingConfig instances provided to PhysicsAnimator for fling gestures. */ private PhysicsAnimator.FlingConfig mFlingConfigX; private PhysicsAnimator.FlingConfig mFlingConfigY; /** FlingConfig instances proviced to PhysicsAnimator for stashing. */ private PhysicsAnimator.FlingConfig mStashConfigX; /** SpringConfig to use for fling-then-spring animations. */ private final PhysicsAnimator.SpringConfig mSpringConfig = Loading Loading @@ -383,6 +386,21 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, void flingToSnapTarget( float velocityX, float velocityY, @Nullable Runnable updateAction, @Nullable Runnable endAction) { movetoTarget(velocityX, velocityY, updateAction, endAction, false /* isStash */); } /** * Stash PiP to the closest edge. */ void stashToEdge( float velocityX, float velocityY, @Nullable Runnable updateAction, @Nullable Runnable endAction) { movetoTarget(velocityX, velocityY, updateAction, endAction, true /* isStash */); } private void movetoTarget( float velocityX, float velocityY, @Nullable Runnable updateAction, @Nullable Runnable endAction, boolean isStash) { // If we're flinging to a snap target now, we're not springing to catch up to the touch // location now. mSpringingToTouch = false; Loading @@ -391,8 +409,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, .spring(FloatProperties.RECT_WIDTH, mBounds.width(), mSpringConfig) .spring(FloatProperties.RECT_HEIGHT, mBounds.height(), mSpringConfig) .flingThenSpring( FloatProperties.RECT_X, velocityX, mFlingConfigX, mSpringConfig, true /* flingMustReachMinOrMax */) FloatProperties.RECT_X, velocityX, isStash ? mStashConfigX : mFlingConfigX, mSpringConfig, true /* flingMustReachMinOrMax */) .flingThenSpring( FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig) .withEndActions(endAction); Loading @@ -402,7 +420,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, (target, values) -> updateAction.run()); } final float xEndValue = velocityX < 0 ? mMovementBounds.left : mMovementBounds.right; final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO); final float leftEdge = isStash ? mMovementBounds.left - offset : mMovementBounds.left; final float rightEdge = isStash ? mMovementBounds.right + offset : mMovementBounds.right; final float xEndValue = velocityX < 0 ? leftEdge : rightEdge; final float estimatedFlingYEndValue = PhysicsAnimator.estimateFlingEndValue( mTemporaryBounds.top, velocityY, mFlingConfigY); Loading Loading @@ -506,6 +528,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, DEFAULT_FRICTION, mMovementBounds.left, mMovementBounds.right); mFlingConfigY = new PhysicsAnimator.FlingConfig( DEFAULT_FRICTION, mMovementBounds.top, mMovementBounds.bottom); final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO); mStashConfigX = new PhysicsAnimator.FlingConfig( DEFAULT_FRICTION, mMovementBounds.left - offset, mMovementBounds.right + offset); } /** Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +39 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.pip.phone; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASHING; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP; import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE; import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL; Loading @@ -33,6 +34,7 @@ import android.graphics.Rect; import android.graphics.drawable.TransitionDrawable; import android.os.Handler; import android.os.RemoteException; import android.provider.DeviceConfig; import android.util.Log; import android.util.Size; import android.view.Gravity; Loading Loading @@ -101,6 +103,13 @@ public class PipTouchHandler { private final AccessibilityManager mAccessibilityManager; private boolean mShowPipMenuOnAnimationEnd = false; /** * Whether PIP stash is enabled or not. When enabled, if at the time of fling-release the * PIP bounds is outside the left/right edge of the screen, it will be shown in "stashed" mode, * where PIP will only show partially. */ private boolean mEnableStash = false; /** * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move * PIP. Loading Loading @@ -306,6 +315,22 @@ public class PipTouchHandler { }); mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView); mEnableStash = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, PIP_STASHING, /* defaultValue = */ false); deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, context.getMainExecutor(), new DeviceConfig.OnPropertiesChangedListener() { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { if (properties.getKeyset().contains(PIP_STASHING)) { mEnableStash = properties.getBoolean( PIP_STASHING, /* defaultValue = */ false); } } }); } private void reloadResources() { Loading Loading @@ -986,9 +1011,20 @@ public class PipTouchHandler { // Reset the touch state on up before the fling settles mTouchState.reset(); final Rect animatingBounds = mMotionHelper.getPossiblyAnimatingBounds(); // If User releases the PIP window while it's out of the display bounds, put // PIP into stashed mode. if (mEnableStash && (animatingBounds.right > mPipBoundsHandler.getDisplayBounds().right || animatingBounds.left < mPipBoundsHandler.getDisplayBounds().left)) { mMotionHelper.stashToEdge(vel.x, vel.y, PipTouchHandler.this::updateDismissFraction /* updateAction */, this::flingEndAction /* endAction */); } else { mMotionHelper.flingToSnapTarget(vel.x, vel.y, PipTouchHandler.this::updateDismissFraction /* updateAction */, this::flingEndAction /* endAction */); } } else if (mTouchState.isDoubleTap()) { // Expand to fullscreen if this is a double tap // the PiP should be frozen until the transition ends Loading Loading
core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +5 −0 Original line number Diff line number Diff line Loading @@ -394,6 +394,11 @@ public final class SystemUiDeviceConfigFlags { */ public static final String PIP_PINCH_RESIZE = "pip_pinch_resize"; /** * (boolean) Whether to enable stashing for PIP. */ public static final String PIP_STASHING = "pip_stashing"; /** * (float) Bottom height in DP for Back Gesture. */ Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +28 −3 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, private static final int EXPAND_STACK_TO_MENU_DURATION = 250; private static final int LEAVE_PIP_DURATION = 300; private static final int SHIFT_DURATION = 300; private static final float STASH_RATIO = 0.25f; /** Friction to use for PIP when it moves via physics fling animations. */ private static final float DEFAULT_FRICTION = 2f; Loading Loading @@ -120,6 +121,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, /** FlingConfig instances provided to PhysicsAnimator for fling gestures. */ private PhysicsAnimator.FlingConfig mFlingConfigX; private PhysicsAnimator.FlingConfig mFlingConfigY; /** FlingConfig instances proviced to PhysicsAnimator for stashing. */ private PhysicsAnimator.FlingConfig mStashConfigX; /** SpringConfig to use for fling-then-spring animations. */ private final PhysicsAnimator.SpringConfig mSpringConfig = Loading Loading @@ -383,6 +386,21 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, void flingToSnapTarget( float velocityX, float velocityY, @Nullable Runnable updateAction, @Nullable Runnable endAction) { movetoTarget(velocityX, velocityY, updateAction, endAction, false /* isStash */); } /** * Stash PiP to the closest edge. */ void stashToEdge( float velocityX, float velocityY, @Nullable Runnable updateAction, @Nullable Runnable endAction) { movetoTarget(velocityX, velocityY, updateAction, endAction, true /* isStash */); } private void movetoTarget( float velocityX, float velocityY, @Nullable Runnable updateAction, @Nullable Runnable endAction, boolean isStash) { // If we're flinging to a snap target now, we're not springing to catch up to the touch // location now. mSpringingToTouch = false; Loading @@ -391,8 +409,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, .spring(FloatProperties.RECT_WIDTH, mBounds.width(), mSpringConfig) .spring(FloatProperties.RECT_HEIGHT, mBounds.height(), mSpringConfig) .flingThenSpring( FloatProperties.RECT_X, velocityX, mFlingConfigX, mSpringConfig, true /* flingMustReachMinOrMax */) FloatProperties.RECT_X, velocityX, isStash ? mStashConfigX : mFlingConfigX, mSpringConfig, true /* flingMustReachMinOrMax */) .flingThenSpring( FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig) .withEndActions(endAction); Loading @@ -402,7 +420,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, (target, values) -> updateAction.run()); } final float xEndValue = velocityX < 0 ? mMovementBounds.left : mMovementBounds.right; final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO); final float leftEdge = isStash ? mMovementBounds.left - offset : mMovementBounds.left; final float rightEdge = isStash ? mMovementBounds.right + offset : mMovementBounds.right; final float xEndValue = velocityX < 0 ? leftEdge : rightEdge; final float estimatedFlingYEndValue = PhysicsAnimator.estimateFlingEndValue( mTemporaryBounds.top, velocityY, mFlingConfigY); Loading Loading @@ -506,6 +528,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, DEFAULT_FRICTION, mMovementBounds.left, mMovementBounds.right); mFlingConfigY = new PhysicsAnimator.FlingConfig( DEFAULT_FRICTION, mMovementBounds.top, mMovementBounds.bottom); final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO); mStashConfigX = new PhysicsAnimator.FlingConfig( DEFAULT_FRICTION, mMovementBounds.left - offset, mMovementBounds.right + offset); } /** Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +39 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.pip.phone; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_STASHING; import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP; import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE; import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL; Loading @@ -33,6 +34,7 @@ import android.graphics.Rect; import android.graphics.drawable.TransitionDrawable; import android.os.Handler; import android.os.RemoteException; import android.provider.DeviceConfig; import android.util.Log; import android.util.Size; import android.view.Gravity; Loading Loading @@ -101,6 +103,13 @@ public class PipTouchHandler { private final AccessibilityManager mAccessibilityManager; private boolean mShowPipMenuOnAnimationEnd = false; /** * Whether PIP stash is enabled or not. When enabled, if at the time of fling-release the * PIP bounds is outside the left/right edge of the screen, it will be shown in "stashed" mode, * where PIP will only show partially. */ private boolean mEnableStash = false; /** * MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move * PIP. Loading Loading @@ -306,6 +315,22 @@ public class PipTouchHandler { }); mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView); mEnableStash = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, PIP_STASHING, /* defaultValue = */ false); deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, context.getMainExecutor(), new DeviceConfig.OnPropertiesChangedListener() { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { if (properties.getKeyset().contains(PIP_STASHING)) { mEnableStash = properties.getBoolean( PIP_STASHING, /* defaultValue = */ false); } } }); } private void reloadResources() { Loading Loading @@ -986,9 +1011,20 @@ public class PipTouchHandler { // Reset the touch state on up before the fling settles mTouchState.reset(); final Rect animatingBounds = mMotionHelper.getPossiblyAnimatingBounds(); // If User releases the PIP window while it's out of the display bounds, put // PIP into stashed mode. if (mEnableStash && (animatingBounds.right > mPipBoundsHandler.getDisplayBounds().right || animatingBounds.left < mPipBoundsHandler.getDisplayBounds().left)) { mMotionHelper.stashToEdge(vel.x, vel.y, PipTouchHandler.this::updateDismissFraction /* updateAction */, this::flingEndAction /* endAction */); } else { mMotionHelper.flingToSnapTarget(vel.x, vel.y, PipTouchHandler.this::updateDismissFraction /* updateAction */, this::flingEndAction /* endAction */); } } else if (mTouchState.isDoubleTap()) { // Expand to fullscreen if this is a double tap // the PiP should be frozen until the transition ends Loading