diff options
8 files changed, 98 insertions, 45 deletions
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl index f4bee575f811..d01c9330dcb2 100644 --- a/core/java/android/view/IPinnedStackListener.aidl +++ b/core/java/android/view/IPinnedStackListener.aidl @@ -67,20 +67,20 @@ oneway interface IPinnedStackListener { void onActionsChanged(in ParceledListSlice actions); /** - * Called by the window manager to notify the listener to save the reentry fraction, + * Called by the window manager to notify the listener to save the reentry fraction and size, * typically when an Activity leaves PiP (picture-in-picture) mode to fullscreen. * {@param componentName} represents the application component of PiP window * while {@param bounds} is the current PiP bounds used to calculate the - * reentry snap fraction. + * reentry snap fraction and size. */ - void onSaveReentrySnapFraction(in ComponentName componentName, in Rect bounds); + void onSaveReentryBounds(in ComponentName componentName, in Rect bounds); /** - * Called by the window manager to notify the listener to reset saved reentry fraction, + * Called by the window manager to notify the listener to reset saved reentry fraction and size, * typically when an Activity enters PiP (picture-in-picture) mode from fullscreen. * {@param componentName} represents the application component of PiP window. */ - void onResetReentrySnapFraction(in ComponentName componentName); + void onResetReentryBounds(in ComponentName componentName); /** * Called when the window manager has detected change on DisplayInfo, or diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java index 1afc67b3de9b..e3623c5f332c 100644 --- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java @@ -360,6 +360,28 @@ public class PipSnapAlgorithm { } /** + * @return the adjusted size so that it conforms to the given aspectRatio, ensuring that the + * minimum edge is at least minEdgeSize. + */ + public Size getSizeForAspectRatio(Size size, float aspectRatio, float minEdgeSize) { + final int smallestSize = Math.min(size.getWidth(), size.getHeight()); + final int minSize = (int) Math.max(minEdgeSize, smallestSize); + + final int width; + final int height; + if (aspectRatio <= 1) { + // Portrait, width is the minimum size. + width = minSize; + height = Math.round(width / aspectRatio); + } else { + // Landscape, height is the minimum size + height = minSize; + width = Math.round(height * aspectRatio); + } + return new Size(width, height); + } + + /** * @return the closest point in {@param points} to the given {@param x} and {@param y}. */ private Point findClosestPoint(int x, int y, Point[] points) { diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java index fe5a57a277a4..8c0ffb82f0ed 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java @@ -83,16 +83,16 @@ public class PinnedStackListenerForwarder extends IPinnedStackListener.Stub { } @Override - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) { + public void onSaveReentryBounds(ComponentName componentName, Rect bounds) { for (PinnedStackListener listener : mListeners) { - listener.onSaveReentrySnapFraction(componentName, bounds); + listener.onSaveReentryBounds(componentName, bounds); } } @Override - public void onResetReentrySnapFraction(ComponentName componentName) { + public void onResetReentryBounds(ComponentName componentName) { for (PinnedStackListener listener : mListeners) { - listener.onResetReentrySnapFraction(componentName); + listener.onResetReentryBounds(componentName); } } @@ -140,9 +140,9 @@ public class PinnedStackListenerForwarder extends IPinnedStackListener.Stub { public void onActionsChanged(ParceledListSlice actions) {} - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) {} + public void onSaveReentryBounds(ComponentName componentName, Rect bounds) {} - public void onResetReentrySnapFraction(ComponentName componentName) {} + public void onResetReentryBounds(ComponentName componentName) {} public void onDisplayInfoChanged(DisplayInfo displayInfo) {} diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java index 686e7db86c3b..f10274a952bc 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java @@ -64,6 +64,7 @@ public class PipBoundsHandler { private IPinnedStackController mPinnedStackController; private ComponentName mLastPipComponentName; private float mReentrySnapFraction = INVALID_SNAP_FRACTION; + private Size mReentrySize = null; private float mDefaultAspectRatio; private float mMinAspectRatio; @@ -162,7 +163,7 @@ public class PipBoundsHandler { public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds, DisplayInfo displayInfo) { getInsetBounds(insetBounds); - final Rect defaultBounds = getDefaultBounds(INVALID_SNAP_FRACTION); + final Rect defaultBounds = getDefaultBounds(INVALID_SNAP_FRACTION, null); normalBounds.set(defaultBounds); if (animatingBounds.isEmpty()) { animatingBounds.set(defaultBounds); @@ -175,26 +176,28 @@ public class PipBoundsHandler { } /** - * Responds to IPinnedStackListener on saving reentry snap fraction + * Responds to IPinnedStackListener on saving reentry snap fraction and size * for a given {@link ComponentName}. */ - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) { + public void onSaveReentryBounds(ComponentName componentName, Rect bounds) { mReentrySnapFraction = getSnapFraction(bounds); + mReentrySize = new Size(bounds.width(), bounds.height()); mLastPipComponentName = componentName; } /** - * Responds to IPinnedStackListener on resetting reentry snap fraction + * Responds to IPinnedStackListener on resetting reentry snap fraction and size * for a given {@link ComponentName}. */ - public void onResetReentrySnapFraction(ComponentName componentName) { + public void onResetReentryBounds(ComponentName componentName) { if (componentName.equals(mLastPipComponentName)) { - onResetReentrySnapFractionUnchecked(); + onResetReentryBoundsUnchecked(); } } - private void onResetReentrySnapFractionUnchecked() { + private void onResetReentryBoundsUnchecked() { mReentrySnapFraction = INVALID_SNAP_FRACTION; + mReentrySize = null; mLastPipComponentName = null; } @@ -233,7 +236,7 @@ public class PipBoundsHandler { public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) { final Rect destinationBounds; if (bounds == null) { - destinationBounds = getDefaultBounds(mReentrySnapFraction); + destinationBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize); } else { destinationBounds = new Rect(bounds); } @@ -245,7 +248,7 @@ public class PipBoundsHandler { return; } mAspectRatio = aspectRatio; - onResetReentrySnapFractionUnchecked(); + onResetReentryBoundsUnchecked(); try { mPinnedStackController.startAnimation(destinationBounds, sourceRectHint, -1 /* animationDuration */); @@ -269,13 +272,14 @@ public class PipBoundsHandler { */ private void transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio, boolean useCurrentMinEdgeSize) { - // Save the snap fraction, calculate the aspect ratio based on screen size + + // Save the snap fraction and adjust the size based on the new aspect ratio. final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds)); - final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize; - final Size size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize, - mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + final Size size = mSnapAlgorithm.getSizeForAspectRatio( + new Size(stackBounds.width(), stackBounds.height()), aspectRatio, minEdgeSize); + final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f); final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f); stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight()); @@ -286,21 +290,20 @@ public class PipBoundsHandler { } /** - * @return the default bounds to show the PIP, if a {@param snapFraction} is provided, then it - * will apply the default bounds to the provided snap fraction. + * @return the default bounds to show the PIP, if a {@param snapFraction} and {@param size} are + * provided, then it will apply the default bounds to the provided snap fraction and size. */ - private Rect getDefaultBounds(float snapFraction) { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - + private Rect getDefaultBounds(float snapFraction, Size size) { final Rect defaultBounds = new Rect(); - final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio, - mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); - if (snapFraction != INVALID_SNAP_FRACTION) { + if (snapFraction != INVALID_SNAP_FRACTION && size != null) { defaultBounds.set(0, 0, size.getWidth(), size.getHeight()); final Rect movementBounds = getMovementBounds(defaultBounds); mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction); } else { + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio, + mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds, 0, Math.max(mIsImeShowing ? mImeHeight : 0, mIsShelfShowing ? mShelfHeight : 0), @@ -364,11 +367,19 @@ public class PipBoundsHandler { * @return the default snap fraction to apply instead of the default gravity when calculating * the default stack bounds when first entering PiP. */ - private float getSnapFraction(Rect stackBounds) { + public float getSnapFraction(Rect stackBounds) { return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds)); } /** + * Applies the given snap fraction to the given stack bounds. + */ + public void applySnapFraction(Rect stackBounds, float snapFraction) { + final Rect movementBounds = getMovementBounds(stackBounds); + mSnapAlgorithm.applySnapFraction(stackBounds, movementBounds, snapFraction); + } + + /** * @return the pixels for a given dp value. */ private int dpToPx(float dpValue, DisplayMetrics dm) { diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index c33b8d9fbd90..a4707cfb4948 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -65,6 +65,7 @@ public class PipManager implements BasePipManager { private final DisplayInfo mTmpDisplayInfo = new DisplayInfo(); private final Rect mTmpInsetBounds = new Rect(); private final Rect mTmpNormalBounds = new Rect(); + private final Rect mReentryBounds = new Rect(); private PipBoundsHandler mPipBoundsHandler; private InputConsumerController mInputConsumerController; @@ -164,13 +165,25 @@ public class PipManager implements BasePipManager { } @Override - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) { - mHandler.post(() -> mPipBoundsHandler.onSaveReentrySnapFraction(componentName, bounds)); + public void onSaveReentryBounds(ComponentName componentName, Rect bounds) { + mHandler.post(() -> { + // On phones, the expansion animation that happens on pip tap before restoring + // to fullscreen makes it so that the bounds received here are the expanded + // bounds. We want to restore to the unexpanded bounds when re-entering pip, + // so we save the bounds before expansion (normal) instead of the current + // bounds. + mReentryBounds.set(mTouchHandler.getNormalBounds()); + // Apply the snap fraction of the current bounds to the normal bounds. + float snapFraction = mPipBoundsHandler.getSnapFraction(bounds); + mPipBoundsHandler.applySnapFraction(mReentryBounds, snapFraction); + // Save reentry bounds (normal non-expand bounds with current position applied). + mPipBoundsHandler.onSaveReentryBounds(componentName, mReentryBounds); + }); } @Override - public void onResetReentrySnapFraction(ComponentName componentName) { - mHandler.post(() -> mPipBoundsHandler.onResetReentrySnapFraction(componentName)); + public void onResetReentryBounds(ComponentName componentName) { + mHandler.post(() -> mPipBoundsHandler.onResetReentryBounds(componentName)); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index f59b372762bd..2e90a3e28841 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -592,6 +592,13 @@ public class PipTouchHandler { } /** + * @return the unexpanded bounds. + */ + public Rect getNormalBounds() { + return mNormalBounds; + } + + /** * Gesture controlling normal movement of the PIP. */ private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 6af50250e0ab..9e50dcaa190a 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -3075,7 +3075,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Reset the last saved PiP snap fraction on removal. - mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent); + mDisplayContent.mPinnedStackControllerLocked.resetReentryBounds(mActivityComponent); mRemovingFromDisplay = false; } @@ -4329,7 +4329,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this); mAppStopped = true; // Reset the last saved PiP snap fraction on app stop. - mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent); + mDisplayContent.mPinnedStackControllerLocked.resetReentryBounds(mActivityComponent); destroySurfaces(); // Remove any starting window that was added for this app if they are still around. removeStartingWindow(); @@ -6572,7 +6572,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A stackBounds = mTmpRect; pinnedStack.getBounds(stackBounds); } - mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction( + mDisplayContent.mPinnedStackControllerLocked.saveReentryBounds( mActivityComponent, stackBounds); } diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index a5b1fda1d73c..0853f1fe76d9 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -236,10 +236,10 @@ class PinnedStackController { /** * Saves the current snap fraction for re-entry of the current activity into PiP. */ - void saveReentrySnapFraction(final ComponentName componentName, final Rect stackBounds) { + void saveReentryBounds(final ComponentName componentName, final Rect stackBounds) { if (mPinnedStackListener == null) return; try { - mPinnedStackListener.onSaveReentrySnapFraction(componentName, stackBounds); + mPinnedStackListener.onSaveReentryBounds(componentName, stackBounds); } catch (RemoteException e) { Slog.e(TAG_WM, "Error delivering save reentry fraction event.", e); } @@ -248,10 +248,10 @@ class PinnedStackController { /** * Resets the last saved snap fraction so that the default bounds will be returned. */ - void resetReentrySnapFraction(ComponentName componentName) { + void resetReentryBounds(ComponentName componentName) { if (mPinnedStackListener == null) return; try { - mPinnedStackListener.onResetReentrySnapFraction(componentName); + mPinnedStackListener.onResetReentryBounds(componentName); } catch (RemoteException e) { Slog.e(TAG_WM, "Error delivering reset reentry fraction event.", e); } |