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

Commit e9981a28 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Revert "Track current resized bounds for resized PIP."" into rvc-dev am: c8f8ec8e

Change-Id: Ic045c2e7e77777051427eac9507e1491b926617d
parents 93d48d19 c8f8ec8e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -225,8 +225,8 @@ public class PipBoundsHandler {
     */
    Rect getDestinationBounds(float aspectRatio, Rect bounds) {
        final Rect destinationBounds;
        if (bounds == null) {
        final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
        if (bounds == null) {
            destinationBounds = new Rect(defaultBounds);
        } else {
            destinationBounds = new Rect(bounds);
+1 −1
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
                // bounds. We want to restore to the unexpanded bounds when re-entering pip,
                // so we save the bounds before expansion (normal) instead of the current
                // bounds.
                mReentryBounds.set(mTouchHandler.getMinBounds());
                mReentryBounds.set(mTouchHandler.getNormalBounds());
                // Apply the snap fraction of the current bounds to the normal bounds.
                float snapFraction = mPipBoundsHandler.getSnapFraction(bounds);
                mPipBoundsHandler.applySnapFraction(mReentryBounds, snapFraction);
+9 −12
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ public class PipResizeGestureHandler {
    private final PointF mDownPoint = new PointF();
    private final Point mMaxSize = new Point();
    private final Point mMinSize = new Point();
    private final Rect mLastResizeBounds = new Rect();
    private final Rect mTmpBounds = new Rect();
    private final int mDelta;

@@ -194,7 +193,11 @@ public class PipResizeGestureHandler {
            }

        } else if (mAllowGesture) {

            final Rect currentPipBounds = mMotionHelper.getBounds();
            Rect newSize = TaskResizingAlgorithm.resizeDrag(ev.getX(), ev.getY(), mDownPoint.x,
                    mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x, mMinSize.y, mMaxSize,
                    true, true);
            mPipBoundsHandler.transformBoundsToAspectRatio(newSize);
            switch (action) {
                case MotionEvent.ACTION_POINTER_DOWN:
                    // We do not support multi touch for resizing via drag
@@ -203,18 +206,12 @@ public class PipResizeGestureHandler {
                case MotionEvent.ACTION_MOVE:
                    // Capture inputs
                    mInputMonitor.pilferPointers();
                    final Rect currentPipBounds = mMotionHelper.getBounds();
                    mLastResizeBounds.set(TaskResizingAlgorithm.resizeDrag(ev.getX(), ev.getY(),
                            mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
                            mMinSize.y, mMaxSize, true, true));
                    mPipBoundsHandler.transformBoundsToAspectRatio(mLastResizeBounds);
                    mPipTaskOrganizer.resizePip(mLastResizeBounds);

                    //TODO: Actually do resize here.
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mPipTaskOrganizer.finishResize(mLastResizeBounds);
                    mLastResizeBounds.setEmpty();
                    //TODO: Finish resize operation here.
                    mMotionHelper.synchronizePinnedStackBounds();
                    mCtrlType = CTRL_NONE;
                    mAllowGesture = false;
                    break;
@@ -226,7 +223,7 @@ public class PipResizeGestureHandler {
        mMaxSize.set(maxX, maxY);
    }

    void updateMinSize(int minX, int minY) {
    void updateMiniSize(int minX, int minY) {
        mMinSize.set(minX, minY);
    }

+50 −83
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.systemui.R;
import com.android.systemui.pip.PipBoundsHandler;
@@ -74,7 +73,7 @@ public class PipTouchHandler {
    private final Context mContext;
    private final IActivityManager mActivityManager;
    private final PipBoundsHandler mPipBoundsHandler;
    private PipResizeGestureHandler mPipResizeGestureHandler;
    private final PipResizeGestureHandler mPipResizeGestureHandler;
    private IPinnedStackController mPinnedStackController;

    private final PipMenuActivityController mMenuController;
@@ -85,22 +84,14 @@ public class PipTouchHandler {

    // The current movement bounds
    private Rect mMovementBounds = new Rect();
    // The current resized bounds, changed by user resize.
    // Note that this is not necessarily the same as PipMotionHelper#getBounds, since it's possible
    // that PIP is currently is in a expanded state (max size) but we still need mResizeBounds to
    // know what size to restore to once expand animation times out.
    @VisibleForTesting Rect mResizedBounds = new Rect();

    // The reference inset bounds, used to determine the dismiss fraction
    private Rect mInsetBounds = new Rect();

    // The reference bounds used to calculate the minimum/maximum target bounds
    // The bound in which PIP enters is the starting/minimum bound, while the expanded/auto-resized
    // bound is the maximum bound.
    private Rect mMinBounds = new Rect();
    @VisibleForTesting Rect mMinMovementBounds = new Rect();
    private Rect mMaxBounds = new Rect();
    @VisibleForTesting Rect mMaxMovementBounds = new Rect();
    // The reference bounds used to calculate the normal/expanded target bounds
    private Rect mNormalBounds = new Rect();
    private Rect mNormalMovementBounds = new Rect();
    private Rect mExpandedBounds = new Rect();
    private Rect mExpandedMovementBounds = new Rect();
    private int mExpandedShortestEdgeSize;

    // Used to workaround an issue where the WM rotation happens before we are notified, allowing
@@ -135,7 +126,7 @@ public class PipTouchHandler {
    private final PipTouchState mTouchState;
    private final FlingAnimationUtils mFlingAnimationUtils;
    private final FloatingContentCoordinator mFloatingContentCoordinator;
    private PipMotionHelper mMotionHelper;
    private final PipMotionHelper mMotionHelper;
    private PipTouchGesture mGesture;

    // Temp vars
@@ -244,16 +235,14 @@ public class PipTouchHandler {

            mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
        }
        mResizedBounds.setEmpty();
        mPipResizeGestureHandler.onActivityUnpinned();
    }

    public void onPinnedStackAnimationEnded() {
        // Always synchronize the motion helper bounds once PiP animations finish
        mMotionHelper.synchronizePinnedStackBounds();

        updateMovementBounds();
        mResizedBounds.set(mMinBounds);
        mPipResizeGestureHandler.updateMiniSize(mMotionHelper.getBounds().width(),
                mMotionHelper.getBounds().height());

        if (mShowPipMenuOnAnimationEnd) {
            mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
@@ -277,10 +266,7 @@ public class PipTouchHandler {
        mShelfHeight = shelfHeight;
    }

    /**
     * Update all the cached bounds (movement, min, max, etc.)
     */
    public void onMovementBoundsChanged(Rect insetBounds, Rect minBounds, Rect curBounds,
    public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect curBounds,
            boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) {
        final int bottomOffset = mIsImeShowing ? mImeHeight : 0;
        final boolean fromDisplayRotationChanged = (mDisplayRotation != displayRotation);
@@ -289,25 +275,23 @@ public class PipTouchHandler {
        }

        // Re-calculate the expanded bounds
        mMinBounds.set(minBounds);
        Rect minMovementBounds = new Rect();
        mSnapAlgorithm.getMovementBounds(mMinBounds, insetBounds, minMovementBounds,
        mNormalBounds = normalBounds;
        Rect normalMovementBounds = new Rect();
        mSnapAlgorithm.getMovementBounds(mNormalBounds, insetBounds, normalMovementBounds,
                bottomOffset);

        // Calculate the expanded size
        float aspectRatio = (float) minBounds.width() / minBounds.height();
        float aspectRatio = (float) normalBounds.width() / normalBounds.height();
        Point displaySize = new Point();
        mContext.getDisplay().getRealSize(displaySize);
        Size maxSize = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio,
        Size expandedSize = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio,
                mExpandedShortestEdgeSize, displaySize.x, displaySize.y);
        mMaxBounds.set(0, 0, maxSize.getWidth(), maxSize.getHeight());
        Rect maxMovementBounds = new Rect();
        mSnapAlgorithm.getMovementBounds(mMaxBounds, insetBounds, maxMovementBounds,
        mExpandedBounds.set(0, 0, expandedSize.getWidth(), expandedSize.getHeight());
        mPipResizeGestureHandler.updateMaxSize(expandedSize.getWidth(), expandedSize.getHeight());
        Rect expandedMovementBounds = new Rect();
        mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
                bottomOffset);

        mPipResizeGestureHandler.updateMinSize(minBounds.width(), minBounds.height());
        mPipResizeGestureHandler.updateMaxSize(mMaxBounds.width(), mMaxBounds.height());

        // The extra offset does not really affect the movement bounds, but are applied based on the
        // current state (ime showing, or shelf offset) when we need to actually shift
        int extraOffset = Math.max(
@@ -324,8 +308,8 @@ public class PipTouchHandler {
                final float offsetBufferPx = BOTTOM_OFFSET_BUFFER_DP
                        * mContext.getResources().getDisplayMetrics().density;
                final Rect toMovementBounds = mMenuState == MENU_STATE_FULL && willResizeMenu()
                        ? new Rect(maxMovementBounds)
                        : new Rect(minMovementBounds);
                        ? new Rect(expandedMovementBounds)
                        : new Rect(normalMovementBounds);
                final int prevBottom = mMovementBounds.bottom - mMovementBoundsExtraOffsets;
                final int toBottom = toMovementBounds.bottom < toMovementBounds.top
                        ? toMovementBounds.bottom
@@ -339,17 +323,17 @@ public class PipTouchHandler {

        // Update the movement bounds after doing the calculations based on the old movement bounds
        // above
        mMinMovementBounds = minMovementBounds;
        mMaxMovementBounds = maxMovementBounds;
        mNormalMovementBounds = normalMovementBounds;
        mExpandedMovementBounds = expandedMovementBounds;
        mDisplayRotation = displayRotation;
        mInsetBounds.set(insetBounds);
        updateMovementBounds();
        updateMovementBounds(mMenuState);
        mMovementBoundsExtraOffsets = extraOffset;

        // If we have a deferred resize, apply it now
        if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {
            mMotionHelper.animateToUnexpandedState(minBounds, mSavedSnapFraction,
                    mMinMovementBounds, mMovementBounds, true /* immediate */);
            mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
                    mNormalMovementBounds, mMovementBounds, true /* immediate */);
            mSavedSnapFraction = -1f;
            mDeferResizeToNormalBoundsUntilRotation = -1;
        }
@@ -403,7 +387,7 @@ public class PipTouchHandler {
            case MotionEvent.ACTION_UP: {
                // Update the movement bounds again if the state has changed since the user started
                // dragging (ie. when the IME shows)
                updateMovementBounds();
                updateMovementBounds(mMenuState);

                if (mGesture.onUp(mTouchState)) {
                    break;
@@ -501,13 +485,11 @@ public class PipTouchHandler {
        if (menuState == MENU_STATE_FULL && mMenuState != MENU_STATE_FULL) {
            // Save the current snap fraction and if we do not drag or move the PiP, then
            // we store back to this snap fraction.  Otherwise, we'll reset the snap
            // fraction and snap to the closest edge.
            // Also save the current resized bounds so when the menu disappears, we can restore it.
            // fraction and snap to the closest edge
            Rect expandedBounds = new Rect(mExpandedBounds);
            if (resize) {
                mResizedBounds.set(mMotionHelper.getBounds());
                Rect expandedBounds = new Rect(mMaxBounds);
                mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
                        mMovementBounds, mMaxMovementBounds);
                        mMovementBounds, mExpandedMovementBounds);
            }
        } else if (menuState == MENU_STATE_NONE && mMenuState == MENU_STATE_FULL) {
            // Try and restore the PiP to the closest edge, using the saved snap fraction
@@ -533,9 +515,9 @@ public class PipTouchHandler {
                }

                if (mDeferResizeToNormalBoundsUntilRotation == -1) {
                    Rect normalBounds = new Rect(mResizedBounds);
                    Rect normalBounds = new Rect(mNormalBounds);
                    mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
                            mMinMovementBounds, mMovementBounds, false /* immediate */);
                            mNormalMovementBounds, mMovementBounds, false /* immediate */);
                    mSavedSnapFraction = -1f;
                }
            } else {
@@ -546,7 +528,7 @@ public class PipTouchHandler {
            }
        }
        mMenuState = menuState;
        updateMovementBounds();
        updateMovementBounds(menuState);
        // If pip menu has dismissed, we should register the A11y ActionReplacingConnection for pip
        // as well, or it can't handle a11y focus and pip menu can't perform any action.
        onRegistrationChanged(menuState == MENU_STATE_NONE);
@@ -562,26 +544,11 @@ public class PipTouchHandler {
        return mMotionHelper;
    }

    @VisibleForTesting
    PipResizeGestureHandler getPipResizeGestureHandler() {
        return mPipResizeGestureHandler;
    }

    @VisibleForTesting
    void setPipResizeGestureHandler(PipResizeGestureHandler pipResizeGestureHandler) {
        mPipResizeGestureHandler = pipResizeGestureHandler;
    }

    @VisibleForTesting
    void setPipMotionHelper(PipMotionHelper pipMotionHelper) {
        mMotionHelper = pipMotionHelper;
    }

    /**
     * @return the unexpanded bounds.
     */
    public Rect getMinBounds() {
        return mMinBounds;
    public Rect getNormalBounds() {
        return mNormalBounds;
    }

    /**
@@ -734,17 +701,17 @@ public class PipTouchHandler {
    };

    /**
     * Updates the current movement bounds based on the current PIP size.
     * Updates the current movement bounds based on whether the menu is currently visible and
     * resized.
     */
    private void updateMovementBounds() {
        Rect movementBounds = new Rect();
        mSnapAlgorithm.getMovementBounds(mMotionHelper.getBounds(), mInsetBounds,
                movementBounds, mIsImeShowing ? mImeHeight : 0);
        mMotionHelper.setCurrentMovementBounds(movementBounds);

        boolean isMenuExpanded = mMenuState == MENU_STATE_FULL;
    private void updateMovementBounds(int menuState) {
        boolean isMenuExpanded = menuState == MENU_STATE_FULL;
        mMovementBounds = isMenuExpanded && willResizeMenu()
                ? mExpandedMovementBounds
                : mNormalMovementBounds;
        mPipBoundsHandler.setMinEdgeSize(
                isMenuExpanded  && willResizeMenu() ? mExpandedShortestEdgeSize : 0);
                isMenuExpanded ? mExpandedShortestEdgeSize : 0);
        mMotionHelper.setCurrentMovementBounds(mMovementBounds);
    }

    /**
@@ -762,18 +729,18 @@ public class PipTouchHandler {
        if (!mEnableResize) {
            return false;
        }
        return mMaxBounds.width() != mMinBounds.width()
                || mMaxBounds.height() != mMinBounds.height();
        return mExpandedBounds.width() != mNormalBounds.width()
                || mExpandedBounds.height() != mNormalBounds.height();
    }

    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + TAG);
        pw.println(innerPrefix + "mMovementBounds=" + mMovementBounds);
        pw.println(innerPrefix + "mMinBounds=" + mMinBounds);
        pw.println(innerPrefix + "mMinMovementBounds=" + mMinMovementBounds);
        pw.println(innerPrefix + "mMaxBounds=" + mMaxBounds);
        pw.println(innerPrefix + "mMaxMovementBounds=" + mMaxMovementBounds);
        pw.println(innerPrefix + "mNormalBounds=" + mNormalBounds);
        pw.println(innerPrefix + "mNormalMovementBounds=" + mNormalMovementBounds);
        pw.println(innerPrefix + "mExpandedBounds=" + mExpandedBounds);
        pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds);
        pw.println(innerPrefix + "mMenuState=" + mMenuState);
        pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
        pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
+0 −168
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.systemui.pip.phone;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Size;
import android.view.DisplayInfo;

import androidx.test.filters.SmallTest;

import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.FloatingContentCoordinator;

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

/**
 * Unit tests against {@link PipTouchHandler}, including but not limited to:
 * - Update movement bounds based on new bounds
 * - Update movement bounds based on IME/shelf
 * - Update movement bounds to PipResizeHandler
 */
@RunWith(AndroidTestingRunner.class)
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class PipTouchHandlerTest extends SysuiTestCase {
    private static final int ROUNDING_ERROR_MARGIN = 10;
    private static final float DEFAULT_ASPECT_RATIO = 1f;
    private static final Rect EMPTY_CURRENT_BOUNDS = null;

    private PipTouchHandler mPipTouchHandler;
    private DisplayInfo mDefaultDisplayInfo;

    @Mock
    private IActivityManager mActivityManager;

    @Mock
    private IActivityTaskManager mIActivityTaskManager;

    @Mock
    private PipMenuActivityController mPipMenuActivityController;

    @Mock
    private InputConsumerController mInputConsumerController;

    @Mock
    private PipBoundsHandler mPipBoundsHandler;

    @Mock
    private PipTaskOrganizer mPipTaskOrganizer;

    @Mock
    private FloatingContentCoordinator mFloatingContentCoordinator;

    @Mock
    private DeviceConfigProxy mDeviceConfigProxy;

    private PipSnapAlgorithm mPipSnapAlgorithm;
    private PipMotionHelper mMotionHelper;
    private PipResizeGestureHandler mPipResizeGestureHandler;

    Rect mInsetBounds;
    Rect mMinBounds;
    Rect mCurBounds;
    boolean mFromImeAdjustment;
    boolean mFromShelfAdjustment;
    int mDisplayRotation;


    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mPipTouchHandler = new PipTouchHandler(mContext, mActivityManager, mIActivityTaskManager,
                mPipMenuActivityController, mInputConsumerController, mPipBoundsHandler,
                mPipTaskOrganizer, mFloatingContentCoordinator, mDeviceConfigProxy);
        mPipSnapAlgorithm = new PipSnapAlgorithm(mContext);
        mMotionHelper = Mockito.spy(mPipTouchHandler.getMotionHelper());
        mPipResizeGestureHandler = Mockito.spy(mPipTouchHandler.getPipResizeGestureHandler());
        mPipTouchHandler.setPipMotionHelper(mMotionHelper);
        mPipTouchHandler.setPipResizeGestureHandler(mPipResizeGestureHandler);

        // Assume a display of 1000 x 1000
        // inset of 10
        mInsetBounds = new Rect(10, 10, 990, 990);
        // minBounds of 100x100 bottom right corner
        mMinBounds = new Rect(890, 890, 990, 990);
        mCurBounds = new Rect();
        mFromImeAdjustment = false;
        mFromShelfAdjustment = false;
        mDisplayRotation = 0;
    }

    @Test
    public void updateMovementBounds_minBounds() {
        Rect expectedMinMovementBounds = new Rect();
        mPipSnapAlgorithm.getMovementBounds(mMinBounds, mInsetBounds, expectedMinMovementBounds, 0);

        mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
                mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);

        assertEquals(expectedMinMovementBounds, mPipTouchHandler.mMinMovementBounds);
        verify(mPipResizeGestureHandler, times(1))
                .updateMinSize(mMinBounds.width(), mMinBounds.height());
    }

    @Test
    public void updateMovementBounds_maxBounds() {
        Point displaySize = new Point();
        mContext.getDisplay().getRealSize(displaySize);
        Size maxSize = mPipSnapAlgorithm.getSizeForAspectRatio(1,
                mContext.getResources().getDimensionPixelSize(
                        R.dimen.pip_expanded_shortest_edge_size), displaySize.x, displaySize.y);
        Rect maxBounds = new Rect(0, 0, maxSize.getWidth(), maxSize.getHeight());
        Rect expectedMaxMovementBounds = new Rect();
        mPipSnapAlgorithm.getMovementBounds(maxBounds, mInsetBounds, expectedMaxMovementBounds, 0);

        mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
                mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);

        assertEquals(expectedMaxMovementBounds, mPipTouchHandler.mMaxMovementBounds);
        verify(mPipResizeGestureHandler, times(1))
                .updateMaxSize(maxBounds.width(), maxBounds.height());
    }

    @Test
    public void updateMovementBounds_withImeAdjustment_movesPip() {
        mFromImeAdjustment = true;
        mPipTouchHandler.onMovementBoundsChanged(mInsetBounds, mMinBounds, mCurBounds,
                mFromImeAdjustment, mFromShelfAdjustment, mDisplayRotation);

        verify(mMotionHelper, times(1)).animateToOffset(any(), anyInt());
    }
}