Merge "Fix resizability in apps using the override min size"

This commit is contained in:
TreeHugger Robot
2020-11-10 03:46:35 +00:00
committed by Android (Google) Code Review
8 changed files with 195 additions and 95 deletions

View File

@@ -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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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