Merge "Fix stashed PiP so it only moves up/down if outside of insets" into udc-dev

This commit is contained in:
Mateusz Cicheński
2023-06-13 17:11:50 +00:00
committed by Android (Google) Code Review
2 changed files with 217 additions and 1 deletions

View File

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

View File

@@ -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);
}
}