Merge "Persist PiP size to be restored on re-entry"

This commit is contained in:
TreeHugger Robot
2019-12-03 21:44:59 +00:00
committed by Android (Google) Code Review
8 changed files with 98 additions and 45 deletions

View File

@@ -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

View File

@@ -359,6 +359,28 @@ public class PipSnapAlgorithm {
return new Size(width, height);
}
/**
* @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}.
*/

View File

@@ -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) {}

View File

@@ -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,10 +367,18 @@ 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.
*/

View File

@@ -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

View File

@@ -591,6 +591,13 @@ public class PipTouchHandler {
return mMotionHelper;
}
/**
* @return the unexpanded bounds.
*/
public Rect getNormalBounds() {
return mNormalBounds;
}
/**
* Gesture controlling normal movement of the PIP.
*/

View File

@@ -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);
}

View File

@@ -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);
}