summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mateusz Cicheński <mateuszc@google.com> 2023-06-13 18:04:43 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2023-06-13 18:04:43 +0000
commiteeb0ec7dd9d9de06f4eef2650bf1c676935b8cd4 (patch)
treefeb4fe628fb24cd882037cae622dab7daa9ec4f2
parent7055f7c4d4f575075b072de73cbc57b736016bf1 (diff)
parent378b9f11563c52d340e75d335a4c330df13dc4c4 (diff)
Merge "Fix stashed PiP so it only moves up/down if outside of insets" into udc-dev am: 378b9f1156
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23647404 Change-Id: I31120a385a6aa83421c0d1e2e605a6dff8215afe Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java209
2 files changed, 217 insertions, 1 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
index fc674a8aa59b..f9332e4bdb2e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java
@@ -63,6 +63,15 @@ public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithmInterfac
if (pipBoundsState.isImeShowing()) {
insets.bottom -= pipBoundsState.getImeHeight();
}
+ // if PiP is stashed we only adjust the vertical position if it's outside of insets and
+ // ignore all keep clear areas, since it's already on the side
+ if (pipBoundsState.isStashed()) {
+ if (startingBounds.bottom > insets.bottom || startingBounds.top < insets.top) {
+ // bring PiP back to be aligned by bottom inset
+ startingBounds.offset(0, insets.bottom - startingBounds.bottom);
+ }
+ return startingBounds;
+ }
Rect pipBounds = new Rect(startingBounds);
boolean shouldApplyGravity = false;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
index 4d7e9e450ceb..cc9e26b2c4f1 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java
@@ -18,6 +18,9 @@ package com.android.wm.shell.pip.phone;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
@@ -26,10 +29,13 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.pip.PipBoundsAlgorithm;
+import com.android.wm.shell.pip.PipBoundsState;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import java.util.Set;
@@ -42,6 +48,10 @@ import java.util.Set;
public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
private PhonePipKeepClearAlgorithm mPipKeepClearAlgorithm;
+
+ @Mock private PipBoundsAlgorithm mMockPipBoundsAlgorithm;
+ @Mock private PipBoundsState mMockPipBoundsState;
+
private static final Rect DISPLAY_BOUNDS = new Rect(0, 0, 1000, 1000);
@Before
@@ -73,7 +83,6 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
@Test
public void findUnoccludedPosition_withCollidingUnrestrictedKeepClearArea_moveBounds() {
- // TODO(b/183746978): update this test to accommodate for the updated algorithm
final Rect inBounds = new Rect(0, 0, 100, 100);
final Rect keepClearRect = new Rect(50, 50, 150, 150);
@@ -93,4 +102,202 @@ public class PhonePipKeepClearAlgorithmTest extends ShellTestCase {
assertEquals(inBounds, outBounds);
}
+
+ @Test
+ public void adjust_withCollidingRestrictedKeepClearArea_moveBounds() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(50, 50, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertFalse(outBounds.contains(keepClearRect));
+ }
+
+ @Test
+ public void adjust_withNonCollidingRestrictedKeepClearArea_boundsUnchanged() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(100, 100, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertFalse(outBounds.contains(keepClearRect));
+ }
+
+ @Test
+ public void adjust_withCollidingRestrictedKeepClearArea_whileStashed_boundsUnchanged() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(50, 50, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(pipBounds, outBounds);
+ }
+
+ @Test
+ public void adjust_withNonCollidingRestrictedKeepClearArea_whileStashed_boundsUnchanged() {
+ final Rect pipBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(100, 100, 150, 150);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ when(mMockPipBoundsState.getRestrictedKeepClearAreas()).thenReturn(Set.of(keepClearRect));
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(pipBounds, outBounds);
+ }
+
+ @Test
+ public void adjust_aboveDisplayBounds_onLeftEdge_appliesBottomLeftGravity() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.top - 50, 100, DISPLAY_BOUNDS.top + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(0f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_belowDisplayBounds_onLeftEdge_appliesBottomLeftGravity() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 50, 100, DISPLAY_BOUNDS.bottom + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(3f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_aboveDisplayBounds_onRightEdge_appliesBottomRightGravity() {
+ final Rect pipBounds = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.top - 50,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.top + 50);
+ final Rect expected = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 100,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(1f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_belowDisplayBounds_onRightEdge_appliesBottomRightGravity() {
+ final Rect pipBounds = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 50,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom + 50);
+ final Rect expected = new Rect(
+ DISPLAY_BOUNDS.right - 100, DISPLAY_BOUNDS.bottom - 100,
+ DISPLAY_BOUNDS.right, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+ when(mMockPipBoundsAlgorithm.getSnapFraction(any(Rect.class))).thenReturn(2f);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_whileStashed_aboveDisplayBounds_alignsToBottomInset() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.top - 50, 100, DISPLAY_BOUNDS.top + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
+
+ @Test
+ public void adjust_whileStashed_belowDisplayBounds_alignsToBottomInset() {
+ final Rect pipBounds = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 50, 100, DISPLAY_BOUNDS.bottom + 50);
+ final Rect expected = new Rect(
+ 0, DISPLAY_BOUNDS.bottom - 100, 100, DISPLAY_BOUNDS.bottom);
+ when(mMockPipBoundsState.getBounds()).thenReturn(pipBounds);
+ when(mMockPipBoundsState.isStashed()).thenReturn(true);
+ doAnswer(invocation -> {
+ Rect arg0 = invocation.getArgument(0);
+ arg0.set(DISPLAY_BOUNDS);
+ return null;
+ }).when(mMockPipBoundsAlgorithm).getInsetBounds(any(Rect.class));
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(
+ mMockPipBoundsState, mMockPipBoundsAlgorithm);
+
+ assertEquals(expected, outBounds);
+ }
}