Merge "Don't save the default size as reentry state"

This commit is contained in:
Jorge Gil
2020-12-10 20:01:10 +00:00
committed by Android (Google) Code Review
7 changed files with 103 additions and 47 deletions

View File

@@ -123,15 +123,16 @@ public class PipBoundsAlgorithm {
/** Returns the destination bounds to place the PIP window on entry. */
public Rect getEntryDestinationBounds() {
final PipBoundsState.PipReentryState reentryState = mPipBoundsState.getReentryState();
final boolean shouldRestoreReentryBounds = reentryState != null;
final Rect destinationBounds = shouldRestoreReentryBounds
final Rect destinationBounds = reentryState != null
? getDefaultBounds(reentryState.getSnapFraction(), reentryState.getSize())
: getDefaultBounds();
return transformBoundsToAspectRatioIfValid(destinationBounds,
final boolean useCurrentSize = reentryState != null && reentryState.getSize() != null;
final Rect r = transformBoundsToAspectRatioIfValid(destinationBounds,
mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */,
shouldRestoreReentryBounds);
useCurrentSize);
return r;
}
/** Returns the current bounds adjusted to the new aspect ratio, if valid. */
@@ -221,24 +222,36 @@ public class PipBoundsAlgorithm {
private Rect getDefaultBounds(float snapFraction, Size size) {
final Rect defaultBounds = new Rect();
if (snapFraction != INVALID_SNAP_FRACTION && size != null) {
// The default bounds are the given size positioned at the given snap fraction.
defaultBounds.set(0, 0, size.getWidth(), size.getHeight());
final Rect movementBounds = getMovementBounds(defaultBounds);
mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
return defaultBounds;
}
// Calculate the default size.
final Size defaultSize;
final Rect insetBounds = new Rect();
getInsetBounds(insetBounds);
final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
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 = getSizeForAspectRatio(mDefaultAspectRatio,
mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
}
// Now that we have the default size, apply the snap fraction if valid or position the
// bounds using the default gravity.
if (snapFraction != INVALID_SNAP_FRACTION) {
defaultBounds.set(0, 0, defaultSize.getWidth(), defaultSize.getHeight());
final Rect movementBounds = getMovementBounds(defaultBounds);
mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
} else {
final Rect insetBounds = new Rect();
getInsetBounds(insetBounds);
final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo();
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 = getSizeForAspectRatio(mDefaultAspectRatio,
mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight);
}
Gravity.apply(mDefaultStackGravity, defaultSize.getWidth(), defaultSize.getHeight(),
insetBounds, 0, Math.max(
mPipBoundsState.isImeShowing() ? mPipBoundsState.getImeHeight() : 0,

View File

@@ -76,6 +76,8 @@ public final class PipBoundsState {
private int mImeHeight;
private boolean mIsShelfShowing;
private int mShelfHeight;
/** Whether the user has resized the PIP manually. */
private boolean mHasUserResizedPip;
private @Nullable Runnable mOnMinimalSizeChangeCallback;
private @Nullable BiConsumer<Boolean, Integer> mOnShelfVisibilityChangeCallback;
@@ -189,8 +191,8 @@ public final class PipBoundsState {
}
/** Save the reentry state to restore to when re-entering PIP mode. */
public void saveReentryState(@NonNull Rect bounds, float fraction) {
mPipReentryState = new PipReentryState(new Size(bounds.width(), bounds.height()), fraction);
public void saveReentryState(Size size, float fraction) {
mPipReentryState = new PipReentryState(size, fraction);
}
/** Returns the saved reentry state. */
@@ -205,6 +207,7 @@ public final class PipBoundsState {
mLastPipComponentName = lastPipComponentName;
if (changed) {
clearReentryState();
setHasUserResizedPip(false);
}
}
@@ -329,6 +332,16 @@ public final class PipBoundsState {
return mShelfHeight;
}
/** Returns whether the user has resized the PIP. */
public boolean hasUserResizedPip() {
return mHasUserResizedPip;
}
/** Set whether the user has resized the PIP. */
public void setHasUserResizedPip(boolean hasUserResizedPip) {
mHasUserResizedPip = hasUserResizedPip;
}
/**
* Registers a callback when the minimal size of PIP that is set by the app changes.
*/
@@ -397,15 +410,15 @@ public final class PipBoundsState {
static final class PipReentryState {
private static final String TAG = PipReentryState.class.getSimpleName();
private final @NonNull Size mSize;
private final @Nullable Size mSize;
private final float mSnapFraction;
PipReentryState(@NonNull Size size, float snapFraction) {
PipReentryState(@Nullable Size size, float snapFraction) {
mSize = size;
mSnapFraction = snapFraction;
}
@NonNull
@Nullable
Size getSize() {
return mSize;
}

View File

@@ -40,6 +40,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.WindowManagerGlobal;
@@ -86,7 +87,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
private final Rect mTmpInsetBounds = new Rect();
protected final Rect mReentryBounds = new Rect();
private boolean mIsInFixedRotation;
private Consumer<Boolean> mPinnedStackAnimationRecentsCallback;
@@ -438,10 +438,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
@Override
public void onPipTransitionStarted(ComponentName activity, int direction, Rect pipBounds) {
if (isOutPipDirection(direction)) {
// Exiting PIP, save the reentry bounds to restore to when re-entering.
updateReentryBounds(pipBounds);
final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mReentryBounds);
mPipBoundsState.saveReentryState(mReentryBounds, snapFraction);
// Exiting PIP, save the reentry state to restore to when re-entering.
saveReentryState(pipBounds);
}
// Disable touches while the animation is running
mTouchHandler.setTouchEnabled(false);
@@ -450,14 +448,16 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac
}
}
/**
* Update the bounds used to save the re-entry size and snap fraction when exiting PIP.
*/
public void updateReentryBounds(Rect bounds) {
final Rect reentryBounds = mTouchHandler.getUserResizeBounds();
float snapFraction = mPipBoundsAlgorithm.getSnapFraction(bounds);
mPipBoundsAlgorithm.applySnapFraction(reentryBounds, snapFraction);
mReentryBounds.set(reentryBounds);
/** Save the state to restore to on re-entry. */
public void saveReentryState(Rect pipBounds) {
float snapFraction = mPipBoundsAlgorithm.getSnapFraction(pipBounds);
if (mPipBoundsState.hasUserResizedPip()) {
final Rect reentryBounds = mTouchHandler.getUserResizeBounds();
final Size reentrySize = new Size(reentryBounds.width(), reentryBounds.height());
mPipBoundsState.saveReentryState(reentrySize, snapFraction);
} else {
mPipBoundsState.saveReentryState(null /* bounds */, snapFraction);
}
}
/**

View File

@@ -410,6 +410,7 @@ public class PipResizeGestureHandler {
mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
null);
mPipBoundsState.setHasUserResizedPip(true);
}
}
}
@@ -462,6 +463,7 @@ public class PipResizeGestureHandler {
true /* useCurrentSize */);
mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds,
null);
mPipBoundsState.setHasUserResizedPip(true);
}
break;
case MotionEvent.ACTION_UP:

View File

@@ -337,7 +337,8 @@ public class PipBoundsAlgorithmTest extends ShellTestCase {
reentryBounds.scale(1.25f);
final float reentrySnapFraction = mPipBoundsAlgorithm.getSnapFraction(reentryBounds);
mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
mPipBoundsState.saveReentryState(
new Size(reentryBounds.width(), reentryBounds.height()), reentrySnapFraction);
final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
assertEquals(reentryBounds.width(), destinationBounds.width());
@@ -351,7 +352,8 @@ public class PipBoundsAlgorithmTest extends ShellTestCase {
reentryBounds.offset(0, -100);
final float reentrySnapFraction = mPipBoundsAlgorithm.getSnapFraction(reentryBounds);
mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
mPipBoundsState.saveReentryState(
new Size(reentryBounds.width(), reentryBounds.height()), reentrySnapFraction);
final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();

View File

@@ -47,7 +47,7 @@ import java.util.function.BiConsumer;
@SmallTest
public class PipBoundsStateTest extends ShellTestCase {
private static final Rect DEFAULT_BOUNDS = new Rect(0, 0, 10, 10);
private static final Size DEFAULT_SIZE = new Size(10, 10);
private static final float DEFAULT_SNAP_FRACTION = 1.0f;
private PipBoundsState mPipBoundsState;
@@ -71,22 +71,22 @@ public class PipBoundsStateTest extends ShellTestCase {
@Test
public void testSetReentryState() {
final Rect bounds = new Rect(0, 0, 100, 100);
final Size size = new Size(100, 100);
final float snapFraction = 0.5f;
mPipBoundsState.saveReentryState(bounds, snapFraction);
mPipBoundsState.saveReentryState(size, snapFraction);
final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
assertEquals(new Size(100, 100), state.getSize());
assertEquals(size, state.getSize());
assertEquals(snapFraction, state.getSnapFraction(), 0.01);
}
@Test
public void testClearReentryState() {
final Rect bounds = new Rect(0, 0, 100, 100);
final Size size = new Size(100, 100);
final float snapFraction = 0.5f;
mPipBoundsState.saveReentryState(bounds, snapFraction);
mPipBoundsState.saveReentryState(size, snapFraction);
mPipBoundsState.clearReentryState();
assertNull(mPipBoundsState.getReentryState());
@@ -95,20 +95,20 @@ public class PipBoundsStateTest extends ShellTestCase {
@Test
public void testSetLastPipComponentName_notChanged_doesNotClearReentryState() {
mPipBoundsState.setLastPipComponentName(mTestComponentName1);
mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
mPipBoundsState.saveReentryState(DEFAULT_SIZE, DEFAULT_SNAP_FRACTION);
mPipBoundsState.setLastPipComponentName(mTestComponentName1);
final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState();
assertNotNull(state);
assertEquals(new Size(DEFAULT_BOUNDS.width(), DEFAULT_BOUNDS.height()), state.getSize());
assertEquals(DEFAULT_SIZE, state.getSize());
assertEquals(DEFAULT_SNAP_FRACTION, state.getSnapFraction(), 0.01);
}
@Test
public void testSetLastPipComponentName_changed_clearReentryState() {
mPipBoundsState.setLastPipComponentName(mTestComponentName1);
mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION);
mPipBoundsState.saveReentryState(DEFAULT_SIZE, DEFAULT_SNAP_FRACTION);
mPipBoundsState.setLastPipComponentName(mTestComponentName2);

View File

@@ -30,10 +30,12 @@ import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
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.Size;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.WindowManagerShellWrapper;
@@ -135,4 +137,28 @@ public class PipControllerTest extends ShellTestCase {
verify(mMockPipBoundsState, never()).setLastPipComponentName(null);
}
@Test
public void saveReentryState_noUserResize_doesNotSaveSize() {
final Rect bounds = new Rect(0, 0, 10, 10);
when(mMockPipBoundsAlgorithm.getSnapFraction(bounds)).thenReturn(1.0f);
when(mMockPipBoundsState.hasUserResizedPip()).thenReturn(false);
mPipController.saveReentryState(bounds);
verify(mMockPipBoundsState).saveReentryState(null, 1.0f);
}
@Test
public void saveReentryState_userHasResized_savesSize() {
final Rect bounds = new Rect(0, 0, 10, 10);
final Rect resizedBounds = new Rect(0, 0, 30, 30);
when(mMockPipBoundsAlgorithm.getSnapFraction(bounds)).thenReturn(1.0f);
when(mMockPipTouchHandler.getUserResizeBounds()).thenReturn(resizedBounds);
when(mMockPipBoundsState.hasUserResizedPip()).thenReturn(true);
mPipController.saveReentryState(bounds);
verify(mMockPipBoundsState).saveReentryState(new Size(30, 30), 1.0f);
}
}