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