diff options
7 files changed, 103 insertions, 47 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java index 22d8ed50c10e..484592e87a20 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java @@ -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, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java index 53aa61477483..4493d38d2144 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java @@ -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; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 46fff85ca58d..4d2760259521 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -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); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index 2f5219c59bf2..02f6231c6ecf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -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: diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java index a65d832359d2..ef9923550fc5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java @@ -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(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java index 4bcca06b592f..8ba301a9ebfa 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java @@ -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); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index 4687d2d9667c..62ffac4fbd3f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -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); + } } |