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:
jorgegil@google.com
2020-11-04 15:45:56 -08:00
parent 31012130c6
commit 2dd597ae41
8 changed files with 195 additions and 95 deletions

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)