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

Commit c5dbf031 authored by Ben Lin's avatar Ben Lin
Browse files

PiP: Add ResizeGestureHandlerTest.

Bug: 180525424
Test: atest PipResizeGestureHandlerTest
Change-Id: Ibfca3f9d8b5b8f50a1b79f74d2348824ac052746
parent c72ac760
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -232,7 +232,8 @@ public class PipResizeGestureHandler {
        }
    }

    private void onInputEvent(InputEvent ev) {
    @VisibleForTesting
    void onInputEvent(InputEvent ev) {
        // Don't allow resize when PiP is stashed.
        if (mPipBoundsState.isStashed()) {
            return;
@@ -366,7 +367,8 @@ public class PipResizeGestureHandler {
        return mIsSysUiStateValid;
    }

    private void onPinchResize(MotionEvent ev) {
    @VisibleForTesting
    void onPinchResize(MotionEvent ev) {
        int action = ev.getActionMasked();

        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
@@ -411,7 +413,7 @@ public class PipResizeGestureHandler {
            if (!mThresholdCrossed
                    && (distanceBetween(mDownSecondPoint, mLastSecondPoint) > mTouchSlop
                            || distanceBetween(mDownPoint, mLastPoint) > mTouchSlop)) {
                mInputMonitor.pilferPointers();
                pilferPointers();
                mThresholdCrossed = true;
                // Reset the down to begin resizing from this point
                mDownPoint.set(mLastPoint);
@@ -548,6 +550,17 @@ public class PipResizeGestureHandler {
        return mUserResizeBounds;
    }

    @VisibleForTesting
    Rect getLastResizeBounds() {
        return mLastResizeBounds;
    }

    @VisibleForTesting
    void pilferPointers() {
        mInputMonitor.pilferPointers();
    }


    @VisibleForTesting public void updateMaxSize(int maxX, int maxY) {
        mMaxSize.set(maxX, maxY);
    }
+224 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.pip.phone;

import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.MotionEvent;

import androidx.test.filters.SmallTest;

import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipSnapAlgorithm;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.pip.PipUiEventLogger;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/**
 * Unit tests against {@link PipResizeGestureHandler}
 */
@RunWith(AndroidTestingRunner.class)
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class PipResizeGestureHandlerTest extends ShellTestCase {
    private static final int STEP_SIZE = 40;
    private final MotionEvent.PointerProperties[] mPp = new MotionEvent.PointerProperties[2];

    @Mock
    private PhonePipMenuController mPhonePipMenuController;

    @Mock
    private PipTaskOrganizer mPipTaskOrganizer;

    @Mock
    private PipDismissTargetHandler mPipDismissTargetHandler;

    @Mock
    private PipTransitionController mMockPipTransitionController;

    @Mock
    private FloatingContentCoordinator mFloatingContentCoordinator;

    @Mock
    private PipUiEventLogger mPipUiEventLogger;

    @Mock
    private ShellExecutor mMainExecutor;

    private PipResizeGestureHandler mPipResizeGestureHandler;

    private PipBoundsState mPipBoundsState;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mPipBoundsState = new PipBoundsState(mContext);
        final PipSnapAlgorithm pipSnapAlgorithm = new PipSnapAlgorithm();
        final PipBoundsAlgorithm pipBoundsAlgorithm = new PipBoundsAlgorithm(mContext,
                mPipBoundsState, pipSnapAlgorithm);
        final PipMotionHelper motionHelper = new PipMotionHelper(mContext, mPipBoundsState,
                mPipTaskOrganizer, mPhonePipMenuController, pipSnapAlgorithm,
                mMockPipTransitionController, mFloatingContentCoordinator);
        mPipResizeGestureHandler = new PipResizeGestureHandler(mContext, pipBoundsAlgorithm,
                mPipBoundsState, motionHelper, mPipTaskOrganizer, mPipDismissTargetHandler,
                (Rect bounds) -> new Rect(), () -> {}, mPipUiEventLogger, mPhonePipMenuController,
                mMainExecutor) {
            @Override
            public void pilferPointers() {
                // Overridden just to avoid calling into InputMonitor.
            }
        };

        for (int i = 0; i < 2; i++) {
            MotionEvent.PointerProperties pointerProperty = new MotionEvent.PointerProperties();
            pointerProperty.id = i;
            pointerProperty.toolType = MotionEvent.TOOL_TYPE_FINGER;
            mPp[i] = pointerProperty;
        }

        mPipResizeGestureHandler.init();
        mPipResizeGestureHandler.onSystemUiStateChanged(true);
    }

    @Test
    public void twoInput_triggersPinchResize_getBigger() {
        assertTrue(mPipResizeGestureHandler.isUsingPinchToZoom());

        int topLeft = 200;
        int bottomRight = 500;
        mPipBoundsState.setBounds(new Rect(topLeft, topLeft, bottomRight, bottomRight));

        // Start inside the PiP bounds first.
        topLeft += STEP_SIZE;
        bottomRight -= STEP_SIZE;
        MotionEvent downEvent =
                obtainMotionEvent(MotionEvent.ACTION_POINTER_DOWN, topLeft, bottomRight);
        assertTrue(mPipResizeGestureHandler.willStartResizeGesture(downEvent));

        // Slowly move outward.
        topLeft -= STEP_SIZE;
        bottomRight += STEP_SIZE;
        MotionEvent moveEvent1 = obtainMotionEvent(MotionEvent.ACTION_MOVE, topLeft, bottomRight);
        mPipResizeGestureHandler.onPinchResize(moveEvent1);

        // Move outward more.
        topLeft -= STEP_SIZE;
        bottomRight += STEP_SIZE;
        MotionEvent moveEvent2 = obtainMotionEvent(MotionEvent.ACTION_MOVE, topLeft, bottomRight);
        mPipResizeGestureHandler.onPinchResize(moveEvent2);

        verify(mPipTaskOrganizer, times(2))
                .scheduleUserResizePip(any(), any(), anyFloat(), any());

        MotionEvent upEvent = obtainMotionEvent(MotionEvent.ACTION_UP, topLeft, bottomRight);
        mPipResizeGestureHandler.onPinchResize(upEvent);

        verify(mPipTaskOrganizer, times(1))
                .scheduleAnimateResizePip(any(), any(), anyInt(), anyFloat(), any());

        assertTrue("The new size should be bigger than the original PiP size.",
                mPipResizeGestureHandler.getLastResizeBounds().width()
                        > mPipBoundsState.getBounds().width());
    }

    @Test
    public void twoInput_triggersPinchResize_getSmaller() {
        assertTrue(mPipResizeGestureHandler.isUsingPinchToZoom());

        int topLeft = 200;
        int bottomRight = 500;
        mPipBoundsState.setBounds(new Rect(topLeft, topLeft, bottomRight, bottomRight));


        topLeft += STEP_SIZE;
        bottomRight -= STEP_SIZE;
        MotionEvent downEvent =
                obtainMotionEvent(MotionEvent.ACTION_POINTER_DOWN, topLeft, bottomRight);
        assertTrue(mPipResizeGestureHandler.willStartResizeGesture(downEvent));

        topLeft += STEP_SIZE;
        bottomRight -= STEP_SIZE;
        MotionEvent moveEvent1 = obtainMotionEvent(MotionEvent.ACTION_MOVE, topLeft, bottomRight);
        mPipResizeGestureHandler.onPinchResize(moveEvent1);

        topLeft += STEP_SIZE;
        bottomRight -= STEP_SIZE;
        MotionEvent moveEvent2 = obtainMotionEvent(MotionEvent.ACTION_MOVE, topLeft, bottomRight);
        mPipResizeGestureHandler.onPinchResize(moveEvent2);

        verify(mPipTaskOrganizer, times(2))
                .scheduleUserResizePip(any(), any(), anyFloat(), any());

        MotionEvent upEvent = obtainMotionEvent(MotionEvent.ACTION_UP, topLeft, bottomRight);
        mPipResizeGestureHandler.onPinchResize(upEvent);

        verify(mPipTaskOrganizer, times(1))
                .scheduleAnimateResizePip(any(), any(), anyInt(), anyFloat(), any());

        assertTrue("The new size should be smaller than the original PiP size.",
                mPipResizeGestureHandler.getLastResizeBounds().width()
                        < mPipBoundsState.getBounds().width());
    }

    private MotionEvent obtainMotionEvent(int action, int topLeft, int bottomRight) {
        final MotionEvent.PointerCoords[] pc = new MotionEvent.PointerCoords[2];
        for (int i = 0; i < 2; i++) {
            MotionEvent.PointerCoords pointerCoord = new MotionEvent.PointerCoords();
            if (i == 0) {
                pointerCoord.x = topLeft;
                pointerCoord.y = topLeft;
            } else {
                pointerCoord.x = bottomRight;
                pointerCoord.y = bottomRight;
            }
            pc[i] = pointerCoord;
        }
        return MotionEvent.obtain(0 /* downTime */,
                System.currentTimeMillis(),
                action,
                2 /* pointerCount */,
                mPp,
                pc,
                0 /* metaState */,
                0 /* buttonState */,
                0 /* xPrecision */,
                0 /* yPrecision */,
                0 /* deviceId */,
                0 /* edgeFlags */,
                0 /* source */,
                0 /* flags */);
    }
}