Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef4a7417 authored by Mateusz Cicheński's avatar Mateusz Cicheński
Browse files

Fix stashed PiP so it only moves up/down if outside of insets

Add unit tests for adjust() method in PhonePipKeepClearAlgorithm.
This covers test cases for applying gravity, moving PiP away from
keep clear areas (which is equivalent to findUnoccludedPosition test
cases), and for ignoring keep clear areas if PiP is stashed, testing
only the up/down movement added by this change.

Bug: 286478425
Test: atest PhonePipKeepClearAlgorithmTest
Test: before http://recall/-/ekEuGtt9d9HWqkUtAzpHx8/dY9IMjhv5eBf0501pUCPKp
Test: after http://recall/-/ekEuGtt9d9HWqkUtAzpHx8/eLrBdqzAKlGiNvFetdIsh9

Change-Id: I478d364a31652f6507d2a289295d336b62d0db81
parent c831c399
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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;
+208 −1
Original line number Diff line number Diff line
@@ -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);
    }
}