Fix resizability in apps using the override min size
Fixes an issue where activities using the manifest min width/height was causing them to not be resizable. This was caused by: 1. transformBoundsToMinimalSize is called on drag resize, which causes the bounds to go back to the minimal size. 2. After fixing 1, drag resizes "jumps" from the minimal size to the default bounds because the normal bounds are not set to the minimal size 3. Reentry bounds are not restored correctly because when calculating the destination bounds, the bounds where always transformed to the minimal size at the end. This CL changes a few things to fix these issues: 1. The minimal size is now considered when calculating the entry bounds or transforming bounds to aspect ratio. This means that instead of calculating the bounds/size using the "default" size and then adjusting to the minimal size, we'll look at whether we should calculate using the default or the minimal size from the very beginning. 2. When the minimal size changes (onTaskAppeared, onTaskInfoChange, swipeToHome), the normal bounds and movement bounds need to be recalculated. The normal bounds are the default bounds, and the default size changes if the minimal size is set or unset. 3. The min edge size used to be set by PipTouchHandler depending on whether PIP is expanded to either expandedMinEdgeSize or 0. It is now set to mDefaultMinEdgeSize if not expanded. This was not causing issues before but it started to with these changes. Also moved the minEdgeSize and overrideMinSize to PipBoundsState as part of b/169373982 Fixes: 172598623 Bug: 169373982 Test: com.android.wm.shell.pip Test: enter pip, expand, resize, reentry bounds, minimal size in manifest, aspect ratio change all work correctly. Change-Id: I4baa46eb641323282fc23fd4499365c83ff38a7d
This commit is contained in:
@@ -58,8 +58,6 @@ public class PipBoundsHandler {
|
||||
private int mDefaultStackGravity;
|
||||
private int mDefaultMinSize;
|
||||
private Point mScreenEdgeInsets;
|
||||
private int mCurrentMinSize;
|
||||
private Size mOverrideMinimalSize;
|
||||
|
||||
private boolean mIsImeShowing;
|
||||
private int mImeHeight;
|
||||
@@ -74,6 +72,7 @@ public class PipBoundsHandler {
|
||||
// resources as it would clobber mAspectRatio when entering PiP from fullscreen which
|
||||
// triggers a configuration change and the resources to be reloaded.
|
||||
mPipBoundsState.setAspectRatio(mDefaultAspectRatio);
|
||||
mPipBoundsState.setMinEdgeSize(mDefaultMinSize);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +86,6 @@ public class PipBoundsHandler {
|
||||
com.android.internal.R.integer.config_defaultPictureInPictureGravity);
|
||||
mDefaultMinSize = res.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
|
||||
mCurrentMinSize = mDefaultMinSize;
|
||||
final String screenEdgeInsetsDpString = res.getString(
|
||||
com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
|
||||
final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
|
||||
@@ -102,14 +100,6 @@ public class PipBoundsHandler {
|
||||
com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Min edge size for {@link PipSnapAlgorithm} to calculate corresponding bounds
|
||||
* @param minEdgeSize
|
||||
*/
|
||||
public void setMinEdgeSize(int minEdgeSize) {
|
||||
mCurrentMinSize = minEdgeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets both shelf visibility and its height if applicable.
|
||||
* @return {@code true} if the internal shelf state is changed, {@code false} otherwise.
|
||||
@@ -167,16 +157,16 @@ public class PipBoundsHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #getDestinationBounds(Rect, Size, boolean)}
|
||||
* See {@link #getDestinationBounds(Rect, boolean)}
|
||||
*/
|
||||
public Rect getDestinationBounds(Rect bounds, Size minimalSize) {
|
||||
return getDestinationBounds(bounds, minimalSize, false /* useCurrentMinEdgeSize */);
|
||||
public Rect getDestinationBounds(Rect bounds) {
|
||||
return getDestinationBounds(bounds, false /* useCurrentMinEdgeSize */);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link Rect} of the destination PiP window bounds.
|
||||
*/
|
||||
public Rect getDestinationBounds(Rect bounds, Size minimalSize, boolean useCurrentMinEdgeSize) {
|
||||
public Rect getDestinationBounds(Rect bounds, boolean useCurrentMinEdgeSize) {
|
||||
boolean isReentryBounds = false;
|
||||
final Rect destinationBounds;
|
||||
if (bounds == null) {
|
||||
@@ -191,7 +181,6 @@ public class PipBoundsHandler {
|
||||
} else {
|
||||
// Get actual default bounds.
|
||||
defaultBounds = getDefaultBounds(INVALID_SNAP_FRACTION, null /* size */);
|
||||
mOverrideMinimalSize = minimalSize;
|
||||
}
|
||||
|
||||
destinationBounds = new Rect(defaultBounds);
|
||||
@@ -306,67 +295,56 @@ public class PipBoundsHandler {
|
||||
&& Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current bound with the currently store aspect ratio.
|
||||
* @param stackBounds
|
||||
*/
|
||||
public void transformBoundsToAspectRatio(Rect stackBounds) {
|
||||
transformBoundsToAspectRatio(stackBounds, mPipBoundsState.getAspectRatio(),
|
||||
true /* useCurrentMinEdgeSize */, true /* useCurrentSize */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current bounds (or the default bounds if there are no current bounds) with the
|
||||
* specified aspect ratio.
|
||||
*/
|
||||
private void transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio,
|
||||
public void transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio,
|
||||
boolean useCurrentMinEdgeSize, boolean useCurrentSize) {
|
||||
// Save the snap fraction and adjust the size based on the new aspect ratio.
|
||||
final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
|
||||
getMovementBounds(stackBounds), mPipBoundsState.getStashedState());
|
||||
final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize;
|
||||
|
||||
final Size overrideMinSize = mPipBoundsState.getOverrideMinSize();
|
||||
final Size size;
|
||||
if (useCurrentMinEdgeSize || useCurrentSize) {
|
||||
// The default minimum edge size, or the override min edge size if set.
|
||||
final int defaultMinEdgeSize = overrideMinSize == null ? mDefaultMinSize
|
||||
: mPipBoundsState.getOverrideMinEdgeSize();
|
||||
final int minEdgeSize = useCurrentMinEdgeSize ? mPipBoundsState.getMinEdgeSize()
|
||||
: defaultMinEdgeSize;
|
||||
// Use the existing size but adjusted to the aspect ratio and min edge size.
|
||||
size = mSnapAlgorithm.getSizeForAspectRatio(
|
||||
new Size(stackBounds.width(), stackBounds.height()), aspectRatio, minEdgeSize);
|
||||
} else {
|
||||
final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
|
||||
size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize,
|
||||
displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
if (overrideMinSize != null) {
|
||||
// The override minimal size is set, use that as the default size making sure it's
|
||||
// adjusted to the aspect ratio.
|
||||
size = adjustSizeToAspectRatio(overrideMinSize, aspectRatio);
|
||||
} else {
|
||||
// Calculate the default size using the display size and default min edge size.
|
||||
final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
|
||||
size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mDefaultMinSize,
|
||||
displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
// apply the override minimal size if applicable, this minimal size is specified by app
|
||||
if (mOverrideMinimalSize != null) {
|
||||
transformBoundsToMinimalSize(stackBounds, aspectRatio, mOverrideMinimalSize);
|
||||
}
|
||||
mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a given bounds to meet the minimal size constraints.
|
||||
* This function assumes the given {@param stackBounds} qualifies {@param aspectRatio}.
|
||||
*/
|
||||
private void transformBoundsToMinimalSize(Rect stackBounds, float aspectRatio,
|
||||
Size minimalSize) {
|
||||
if (minimalSize == null) return;
|
||||
final Size adjustedMinimalSize;
|
||||
final float minimalSizeAspectRatio =
|
||||
minimalSize.getWidth() / (float) minimalSize.getHeight();
|
||||
if (minimalSizeAspectRatio > aspectRatio) {
|
||||
// minimal size is wider, fixed the width and increase the height
|
||||
adjustedMinimalSize = new Size(
|
||||
minimalSize.getWidth(), (int) (minimalSize.getWidth() / aspectRatio));
|
||||
/** Adjusts the given size to conform to the given aspect ratio. */
|
||||
private Size adjustSizeToAspectRatio(@NonNull Size size, float aspectRatio) {
|
||||
final float sizeAspectRatio = size.getWidth() / (float) size.getHeight();
|
||||
if (sizeAspectRatio > aspectRatio) {
|
||||
// Size is wider, fix the width and increase the height
|
||||
return new Size(size.getWidth(), (int) (size.getWidth() / aspectRatio));
|
||||
} else {
|
||||
adjustedMinimalSize = new Size(
|
||||
(int) (minimalSize.getHeight() * aspectRatio), minimalSize.getHeight());
|
||||
// Size is taller, fix the height and adjust the width.
|
||||
return new Size((int) (size.getHeight() * aspectRatio), size.getHeight());
|
||||
}
|
||||
final Rect containerBounds = new Rect(stackBounds);
|
||||
Gravity.apply(mDefaultStackGravity,
|
||||
adjustedMinimalSize.getWidth(), adjustedMinimalSize.getHeight(),
|
||||
containerBounds, stackBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,12 +361,20 @@ public class PipBoundsHandler {
|
||||
final Rect insetBounds = new Rect();
|
||||
getInsetBounds(insetBounds);
|
||||
final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
|
||||
size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
|
||||
mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
|
||||
0, Math.max(mIsImeShowing ? mImeHeight : 0,
|
||||
mIsShelfShowing ? mShelfHeight : 0),
|
||||
defaultBounds);
|
||||
final Size defaultSize;
|
||||
final Size overrideMinSize = mPipBoundsState.getOverrideMinSize();
|
||||
if (overrideMinSize != null) {
|
||||
// The override minimal size is set, use that as the default size making sure it's
|
||||
// adjusted to the aspect ratio.
|
||||
defaultSize = adjustSizeToAspectRatio(overrideMinSize, mDefaultAspectRatio);
|
||||
} else {
|
||||
// Calculate the default size using the display size and default min edge size.
|
||||
defaultSize = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
|
||||
mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
|
||||
}
|
||||
Gravity.apply(mDefaultStackGravity, defaultSize.getWidth(), defaultSize.getHeight(),
|
||||
insetBounds, 0, Math.max(mIsImeShowing ? mImeHeight : 0,
|
||||
mIsShelfShowing ? mShelfHeight : 0), defaultBounds);
|
||||
}
|
||||
return defaultBounds;
|
||||
}
|
||||
@@ -443,6 +429,10 @@ public class PipBoundsHandler {
|
||||
mSnapAlgorithm.applySnapFraction(stackBounds, movementBounds, snapFraction);
|
||||
}
|
||||
|
||||
public int getDefaultMinSize() {
|
||||
return mDefaultMinSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pixels for a given dp value.
|
||||
*/
|
||||
|
||||
@@ -61,8 +61,14 @@ public final class PipBoundsState {
|
||||
private ComponentName mLastPipComponentName;
|
||||
private final DisplayInfo mDisplayInfo = new DisplayInfo();
|
||||
private final DisplayLayout mDisplayLayout = new DisplayLayout();
|
||||
/** The current minimum edge size of PIP. */
|
||||
private int mMinEdgeSize;
|
||||
/** The preferred minimum (and default) size specified by apps. */
|
||||
private Size mOverrideMinSize;
|
||||
private final @NonNull AnimatingBoundsState mAnimatingBoundsState = new AnimatingBoundsState();
|
||||
|
||||
private Runnable mOnMinimalSizeChangeCallback;
|
||||
|
||||
public PipBoundsState(Context context) {
|
||||
mContext = context;
|
||||
reloadResources();
|
||||
@@ -203,10 +209,49 @@ public final class PipBoundsState {
|
||||
mPipReentryState = null;
|
||||
}
|
||||
|
||||
/** Set the PIP minimum edge size. */
|
||||
public void setMinEdgeSize(int minEdgeSize) {
|
||||
mMinEdgeSize = minEdgeSize;
|
||||
}
|
||||
|
||||
/** Returns the PIP's current minimum edge size. */
|
||||
public int getMinEdgeSize() {
|
||||
return mMinEdgeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preferred size of PIP as specified by the activity in PIP mode.
|
||||
*/
|
||||
public void setOverrideMinSize(Size overrideMinSize) {
|
||||
final boolean changed = !Objects.equals(overrideMinSize, mOverrideMinSize);
|
||||
mOverrideMinSize = overrideMinSize;
|
||||
if (changed && mOnMinimalSizeChangeCallback != null) {
|
||||
mOnMinimalSizeChangeCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the preferred minimal size specified by the activity in PIP. */
|
||||
public Size getOverrideMinSize() {
|
||||
return mOverrideMinSize;
|
||||
}
|
||||
|
||||
/** Returns the minimum edge size of the override minimum size, or 0 if not set. */
|
||||
public int getOverrideMinEdgeSize() {
|
||||
if (mOverrideMinSize == null) return 0;
|
||||
return Math.min(mOverrideMinSize.getWidth(), mOverrideMinSize.getHeight());
|
||||
}
|
||||
|
||||
public AnimatingBoundsState getAnimatingBoundsState() {
|
||||
return mAnimatingBoundsState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback when the minimal size of PIP that is set by the app changes.
|
||||
*/
|
||||
public void setOnMinimalSizeChangeCallback(Runnable onMinimalSizeChangeCallback) {
|
||||
mOnMinimalSizeChangeCallback = onMinimalSizeChangeCallback;
|
||||
}
|
||||
|
||||
/** Source of truth for the current animation bounds of PIP. */
|
||||
public static class AnimatingBoundsState {
|
||||
/** The bounds used when PIP is being dragged or animated. */
|
||||
@@ -298,6 +343,8 @@ public final class PipBoundsState {
|
||||
pw.println(innerPrefix + "mDisplayLayout=" + mDisplayLayout);
|
||||
pw.println(innerPrefix + "mStashedState=" + mStashedState);
|
||||
pw.println(innerPrefix + "mStashOffset=" + mStashOffset);
|
||||
pw.println(innerPrefix + "mMinEdgeSize=" + mMinEdgeSize);
|
||||
pw.println(innerPrefix + "mOverrideMinSize=" + mOverrideMinSize);
|
||||
if (mPipReentryState == null) {
|
||||
pw.println(innerPrefix + "mPipReentryState=null");
|
||||
} else {
|
||||
|
||||
@@ -339,10 +339,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
PictureInPictureParams pictureInPictureParams) {
|
||||
mShouldIgnoreEnteringPipTransition = true;
|
||||
sendOnPipTransitionStarted(componentName, TRANSITION_DIRECTION_TO_PIP);
|
||||
mPipBoundsState.setLastPipComponentName(componentName);
|
||||
mPipBoundsState.setAspectRatio(getAspectRatioOrDefault(pictureInPictureParams));
|
||||
return mPipBoundsHandler.getDestinationBounds(null /* bounds */,
|
||||
getMinimalSize(activityInfo));
|
||||
setBoundsStateForEntry(componentName, pictureInPictureParams, activityInfo);
|
||||
return mPipBoundsHandler.getDestinationBounds(null /* bounds */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,6 +354,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
}
|
||||
}
|
||||
|
||||
private void setBoundsStateForEntry(ComponentName componentName, PictureInPictureParams params,
|
||||
ActivityInfo activityInfo) {
|
||||
mPipBoundsState.setLastPipComponentName(componentName);
|
||||
mPipBoundsState.setAspectRatio(getAspectRatioOrDefault(params));
|
||||
mPipBoundsState.setOverrideMinSize(getMinimalSize(activityInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands PiP to the previous bounds, this is done in two phases using
|
||||
* {@link WindowContainerTransaction}
|
||||
@@ -483,7 +488,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mLeash = leash;
|
||||
mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
|
||||
mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
|
||||
mPipBoundsState.setLastPipComponentName(mTaskInfo.topActivity);
|
||||
setBoundsStateForEntry(mTaskInfo.topActivity, mPictureInPictureParams,
|
||||
mTaskInfo.topActivityInfo);
|
||||
|
||||
mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo);
|
||||
mPipUiEventLoggerLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER);
|
||||
@@ -520,9 +526,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
return;
|
||||
}
|
||||
|
||||
mPipBoundsState.setAspectRatio(getAspectRatioOrDefault(mPictureInPictureParams));
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(null /* bounds */,
|
||||
getMinimalSize(mTaskInfo.topActivityInfo));
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(null /* bounds */);
|
||||
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
|
||||
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
|
||||
|
||||
@@ -675,6 +679,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
||||
Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
|
||||
mPipBoundsState.setLastPipComponentName(info.topActivity);
|
||||
mPipBoundsState.setOverrideMinSize(getMinimalSize(info.topActivityInfo));
|
||||
final PictureInPictureParams newParams = info.pictureInPictureParams;
|
||||
if (newParams == null || !applyPictureInPictureParams(newParams)) {
|
||||
Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams);
|
||||
@@ -682,8 +687,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
}
|
||||
// Aspect ratio changed, re-calculate destination bounds.
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
mPipBoundsState.getBounds(), getMinimalSize(info.topActivityInfo),
|
||||
true /* userCurrentMinEdgeSize */);
|
||||
mPipBoundsState.getBounds(), true /* useCurrentMinEdgeSize */);
|
||||
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
|
||||
scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
|
||||
null /* updateBoundsCallback */);
|
||||
@@ -698,7 +702,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
public void onFixedRotationFinished(int displayId) {
|
||||
if (mShouldDeferEnteringPip && mState.isInPip()) {
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
|
||||
null /* bounds */);
|
||||
// schedule a regular animation to ensure all the callbacks are still being sent
|
||||
enterPipWithAlphaAnimation(destinationBounds, 0 /* durationMs */);
|
||||
}
|
||||
@@ -773,8 +777,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
return;
|
||||
}
|
||||
|
||||
final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(null /* bounds */,
|
||||
getMinimalSize(mTaskInfo.topActivityInfo));
|
||||
final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(null /* bounds */);
|
||||
if (newDestinationBounds.equals(currentDestinationBounds)) return;
|
||||
if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
|
||||
animator.updateEndValue(newDestinationBounds);
|
||||
|
||||
@@ -242,9 +242,16 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
|
||||
displayController.getDisplay(displayId).getDisplayInfo(newDisplayInfo);
|
||||
mPipBoundsState.setDisplayInfo(newDisplayInfo);
|
||||
updateMovementBounds(null /* toBounds */, false /* fromRotation */,
|
||||
false /* fromImeAdjustment */, false /* fromShelfAdustment */,
|
||||
false /* fromImeAdjustment */, false /* fromShelfAdjustment */,
|
||||
null /* wct */);
|
||||
});
|
||||
mPipBoundsState.setOnMinimalSizeChangeCallback(
|
||||
() -> {
|
||||
// The minimal size drives the normal bounds, so they need to be recalculated.
|
||||
updateMovementBounds(null /* toBounds */, false /* fromRotation */,
|
||||
false /* fromImeAdjustment */, false /* fromShelfAdjustment */,
|
||||
null /* wct */);
|
||||
});
|
||||
mMediaController = pipMediaController;
|
||||
mMenuController = pipMenuActivityController;
|
||||
mTouchHandler = pipTouchHandler;
|
||||
|
||||
@@ -451,7 +451,9 @@ public class PipResizeGestureHandler {
|
||||
mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
|
||||
mMinSize.y, mMaxSize, true,
|
||||
mLastDownBounds.width() > mLastDownBounds.height()));
|
||||
mPipBoundsHandler.transformBoundsToAspectRatio(mLastResizeBounds);
|
||||
mPipBoundsHandler.transformBoundsToAspectRatio(mLastResizeBounds,
|
||||
mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */,
|
||||
true /* useCurrentSize */);
|
||||
mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
|
||||
null);
|
||||
}
|
||||
|
||||
@@ -848,8 +848,9 @@ public class PipTouchHandler {
|
||||
mMotionHelper.setCurrentMovementBounds(mMovementBounds);
|
||||
|
||||
boolean isMenuExpanded = mMenuState == MENU_STATE_FULL;
|
||||
mPipBoundsHandler.setMinEdgeSize(
|
||||
isMenuExpanded && willResizeMenu() ? mExpandedShortestEdgeSize : 0);
|
||||
mPipBoundsState.setMinEdgeSize(
|
||||
isMenuExpanded && willResizeMenu() ? mExpandedShortestEdgeSize
|
||||
: mPipBoundsHandler.getDefaultMinSize());
|
||||
}
|
||||
|
||||
private Rect getMovementBounds(Rect curBounds) {
|
||||
|
||||
@@ -124,7 +124,7 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
for (float aspectRatio : aspectRatios) {
|
||||
mPipBoundsState.setAspectRatio(aspectRatio);
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
final float actualAspectRatio =
|
||||
destinationBounds.width() / (destinationBounds.height() * 1f);
|
||||
assertEquals("Destination bounds matches the given aspect ratio",
|
||||
@@ -141,7 +141,7 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
for (float aspectRatio : invalidAspectRatios) {
|
||||
mPipBoundsState.setAspectRatio(aspectRatio);
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
final float actualAspectRatio =
|
||||
destinationBounds.width() / (destinationBounds.height() * 1f);
|
||||
assertEquals("Destination bounds fallbacks to default aspect ratio",
|
||||
@@ -157,8 +157,7 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
|
||||
|
||||
mPipBoundsState.setAspectRatio(aspectRatio);
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(currentBounds,
|
||||
EMPTY_MINIMAL_SIZE);
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(currentBounds);
|
||||
|
||||
final float actualAspectRatio =
|
||||
destinationBounds.width() / (destinationBounds.height() * 1f);
|
||||
@@ -182,8 +181,9 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
final float aspectRatio = aspectRatios[i];
|
||||
final Size minimalSize = minimalSizes[i];
|
||||
mPipBoundsState.setAspectRatio(aspectRatio);
|
||||
mPipBoundsState.setOverrideMinSize(minimalSize);
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, minimalSize);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
assertTrue("Destination bounds is no smaller than minimal requirement",
|
||||
(destinationBounds.width() == minimalSize.getWidth()
|
||||
&& destinationBounds.height() >= minimalSize.getHeight())
|
||||
@@ -204,8 +204,9 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);
|
||||
|
||||
mPipBoundsState.setAspectRatio(aspectRatio);
|
||||
mPipBoundsState.setOverrideMinSize(minSize);
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
currentBounds, minSize);
|
||||
currentBounds, true /* useCurrentMinEdgeSize */);
|
||||
|
||||
assertTrue("Destination bounds ignores minimal size",
|
||||
destinationBounds.width() > minSize.getWidth()
|
||||
@@ -216,13 +217,13 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
public void getDestinationBounds_reentryStateExists_restoreLastSize() {
|
||||
mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||
final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
reentryBounds.scale(1.25f);
|
||||
final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
|
||||
|
||||
mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
assertEquals(reentryBounds.width(), destinationBounds.width());
|
||||
assertEquals(reentryBounds.height(), destinationBounds.height());
|
||||
@@ -232,14 +233,14 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
public void getDestinationBounds_reentryStateExists_restoreLastPosition() {
|
||||
mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||
final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
reentryBounds.offset(0, -100);
|
||||
final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
|
||||
|
||||
mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
|
||||
|
||||
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
assertBoundsInclusionWithMargin("restoreLastPosition", reentryBounds, destinationBounds);
|
||||
}
|
||||
@@ -249,11 +250,11 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
final int shelfHeight = 100;
|
||||
mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||
final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
mPipBoundsHandler.setShelfHeight(true, shelfHeight);
|
||||
final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
oldPosition.offset(0, -shelfHeight);
|
||||
assertBoundsInclusionWithMargin("offsetBounds by shelf", oldPosition, newPosition);
|
||||
@@ -264,11 +265,11 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
final int imeHeight = 100;
|
||||
mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||
final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
|
||||
final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
oldPosition.offset(0, -imeHeight);
|
||||
assertBoundsInclusionWithMargin("offsetBounds by IME", oldPosition, newPosition);
|
||||
@@ -278,12 +279,12 @@ public class PipBoundsHandlerTest extends ShellTestCase {
|
||||
public void getDestinationBounds_noReentryState_useDefaultBounds() {
|
||||
mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
|
||||
final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
mPipBoundsState.clearReentryState();
|
||||
|
||||
final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(
|
||||
EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
|
||||
EMPTY_CURRENT_BOUNDS);
|
||||
|
||||
assertBoundsInclusionWithMargin("useDefaultBounds", defaultBounds, actualBounds);
|
||||
}
|
||||
|
||||
@@ -30,12 +30,14 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.PictureInPictureParams;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.util.Rational;
|
||||
import android.util.Size;
|
||||
import android.view.DisplayInfo;
|
||||
import android.window.WindowContainerToken;
|
||||
|
||||
@@ -113,6 +115,15 @@ public class PipTaskOrganizerTest extends ShellTestCase {
|
||||
assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startSwipePipToHome_updatesOverrideMinSize() {
|
||||
final Size minSize = new Size(100, 80);
|
||||
|
||||
mSpiedPipTaskOrganizer.startSwipePipToHome(mComponent1, createActivityInfo(minSize), null);
|
||||
|
||||
assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTaskAppeared_updatesAspectRatio() {
|
||||
final Rational aspectRatio = new Rational(2, 1);
|
||||
@@ -131,6 +142,17 @@ public class PipTaskOrganizerTest extends ShellTestCase {
|
||||
assertEquals(mComponent1, mPipBoundsState.getLastPipComponentName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTaskAppeared_updatesOverrideMinSize() {
|
||||
final Size minSize = new Size(100, 80);
|
||||
|
||||
mSpiedPipTaskOrganizer.onTaskAppeared(
|
||||
createTaskInfo(mComponent1, createPipParams(null), minSize),
|
||||
null /* leash */);
|
||||
|
||||
assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTaskInfoChanged_updatesAspectRatioIfChanged() {
|
||||
final Rational startAspectRatio = new Rational(2, 1);
|
||||
@@ -155,11 +177,23 @@ public class PipTaskOrganizerTest extends ShellTestCase {
|
||||
assertEquals(mComponent2, mPipBoundsState.getLastPipComponentName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTaskInfoChanged_updatesOverrideMinSize() {
|
||||
mSpiedPipTaskOrganizer.onTaskAppeared(createTaskInfo(mComponent1,
|
||||
createPipParams(null)), null /* leash */);
|
||||
|
||||
final Size minSize = new Size(100, 80);
|
||||
mSpiedPipTaskOrganizer.onTaskInfoChanged(createTaskInfo(mComponent2,
|
||||
createPipParams(null), minSize));
|
||||
|
||||
assertEquals(minSize, mPipBoundsState.getOverrideMinSize());
|
||||
}
|
||||
|
||||
private void preparePipTaskOrg() {
|
||||
final DisplayInfo info = new DisplayInfo();
|
||||
mPipBoundsState.setDisplayInfo(info);
|
||||
when(mMockPipBoundsHandler.getDestinationBounds(any(), any())).thenReturn(new Rect());
|
||||
when(mMockPipBoundsHandler.getDestinationBounds(any(), any(), anyBoolean()))
|
||||
when(mMockPipBoundsHandler.getDestinationBounds(any())).thenReturn(new Rect());
|
||||
when(mMockPipBoundsHandler.getDestinationBounds(any(), anyBoolean()))
|
||||
.thenReturn(new Rect());
|
||||
mPipBoundsState.setDisplayInfo(info);
|
||||
mSpiedPipTaskOrganizer.setOneShotAnimationType(PipAnimationController.ANIM_TYPE_ALPHA);
|
||||
@@ -169,13 +203,28 @@ public class PipTaskOrganizerTest extends ShellTestCase {
|
||||
|
||||
private static ActivityManager.RunningTaskInfo createTaskInfo(
|
||||
ComponentName componentName, PictureInPictureParams params) {
|
||||
return createTaskInfo(componentName, params, null /* minSize */);
|
||||
}
|
||||
|
||||
private static ActivityManager.RunningTaskInfo createTaskInfo(
|
||||
ComponentName componentName, PictureInPictureParams params, Size minSize) {
|
||||
final ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
||||
info.token = mock(WindowContainerToken.class);
|
||||
info.pictureInPictureParams = params;
|
||||
info.topActivity = componentName;
|
||||
if (minSize != null) {
|
||||
info.topActivityInfo = createActivityInfo(minSize);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
private static ActivityInfo createActivityInfo(Size minSize) {
|
||||
final ActivityInfo activityInfo = new ActivityInfo();
|
||||
activityInfo.windowLayout = new ActivityInfo.WindowLayout(
|
||||
0, 0, 0, 0, 0, minSize.getWidth(), minSize.getHeight());
|
||||
return activityInfo;
|
||||
}
|
||||
|
||||
private static PictureInPictureParams createPipParams(Rational aspectRatio) {
|
||||
return new PictureInPictureParams.Builder()
|
||||
.setAspectRatio(aspectRatio)
|
||||
|
||||
Reference in New Issue
Block a user