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

Commit 4cd3e8c0 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fixing issue with PIP while IME is showing."

parents 46fff5e9 14fefc26
Loading
Loading
Loading
Loading
+92 −14
Original line number Diff line number Diff line
@@ -53,7 +53,14 @@ public class PipSnapAlgorithm {

    public PipSnapAlgorithm(Context context) {
        mContext = context;
        mOrientation = context.getResources().getConfiguration().orientation;
        onConfigurationChanged();
    }

    /**
     * Updates the snap algorithm when the configuration changes.
     */
    public void onConfigurationChanged() {
        mOrientation = mContext.getResources().getConfiguration().orientation;
        calculateSnapTargets();
    }

@@ -90,19 +97,7 @@ public class PipSnapAlgorithm {
        final Rect newBounds = new Rect(stackBounds);
        if (mSnapMode == SNAP_MODE_EDGE) {
            // Find the closest edge to the given stack bounds and snap to it
            final int fromLeft = stackBounds.left - movementBounds.left;
            final int fromTop = stackBounds.top - movementBounds.top;
            final int fromRight = movementBounds.right - stackBounds.left;
            final int fromBottom = movementBounds.bottom - stackBounds.top;
            if (fromLeft <= fromTop && fromLeft <= fromRight && fromLeft <= fromBottom) {
                newBounds.offset(-fromLeft, 0);
            } else if (fromTop <= fromLeft && fromTop <= fromRight && fromTop <= fromBottom) {
                newBounds.offset(0, -fromTop);
            } else if (fromRight < fromLeft && fromRight < fromTop && fromRight < fromBottom) {
                newBounds.offset(fromRight, 0);
            } else {
                newBounds.offset(0, fromBottom);
            }
            snapRectToClosestEdge(stackBounds, movementBounds, newBounds);
        } else {
            // Find the closest snap point
            final Rect tmpBounds = new Rect();
@@ -118,6 +113,68 @@ public class PipSnapAlgorithm {
        return newBounds;
    }

    /**
     * @return returns a fraction that describes where along the {@param movementBounds} the
     *         {@param stackBounds} are. If the {@param stackBounds} are not currently on the
     *         {@param movementBounds} exactly, then they will be snapped to the movement bounds.
     *
     *         The fraction is defined in a clockwise fashion against the {@param movementBounds}:
     *
     *            0   1
     *          4 +---+ 1
     *            |   |
     *          3 +---+ 2
     *            3   2
     */
    public float getSnapFraction(Rect stackBounds, Rect movementBounds) {
        final Rect tmpBounds = new Rect();
        snapRectToClosestEdge(stackBounds, movementBounds, tmpBounds);
        final float widthFraction = (float) (tmpBounds.left - movementBounds.left) /
                movementBounds.width();
        final float heightFraction = (float) (tmpBounds.top - movementBounds.top) /
                movementBounds.height();
        if (tmpBounds.top == movementBounds.top) {
            return widthFraction;
        } else if (tmpBounds.left == movementBounds.right) {
            return 1f + heightFraction;
        } else if (tmpBounds.top == movementBounds.bottom) {
            return 2f + (1f - widthFraction);
        } else {
            return 3f + (1f - heightFraction);
        }
    }

    /**
     * Moves the {@param stackBounds} along the {@param movementBounds} to the given snap fraction.
     * See {@link #getSnapFraction(Rect, Rect)}.
     *
     * The fraction is define in a clockwise fashion against the {@param movementBounds}:
     *
     *    0   1
     *  4 +---+ 1
     *    |   |
     *  3 +---+ 2
     *    3   2
     */
    public void applySnapFraction(Rect stackBounds, Rect movementBounds, float snapFraction) {
        if (snapFraction < 1f) {
            int offset = movementBounds.left + (int) (snapFraction * movementBounds.width());
            stackBounds.offsetTo(offset, movementBounds.top);
        } else if (snapFraction < 2f) {
            snapFraction -= 1f;
            int offset = movementBounds.top + (int) (snapFraction * movementBounds.height());
            stackBounds.offsetTo(movementBounds.right, offset);
        } else if (snapFraction < 3f) {
            snapFraction -= 2f;
            int offset = movementBounds.left + (int) ((1f - snapFraction) * movementBounds.width());
            stackBounds.offsetTo(offset, movementBounds.bottom);
        } else {
            snapFraction -= 3f;
            int offset = movementBounds.top + (int) ((1f - snapFraction) * movementBounds.height());
            stackBounds.offsetTo(movementBounds.left, offset);
        }
    }

    /**
     * @return the closest point in {@param points} to the given {@param x} and {@param y}.
     */
@@ -134,6 +191,27 @@ public class PipSnapAlgorithm {
        return closestPoint;
    }

    /**
     * Snaps the {@param stackBounds} to the closest edge of the {@param movementBounds} and writes
     * the new bounds out to {@param boundsOut}.
     */
    private void snapRectToClosestEdge(Rect stackBounds, Rect movementBounds, Rect boundsOut) {
        final int fromLeft = Math.abs(stackBounds.left - movementBounds.left);
        final int fromTop = Math.abs(stackBounds.top - movementBounds.top);
        final int fromRight = Math.abs(movementBounds.right - stackBounds.left);
        final int fromBottom = Math.abs(movementBounds.bottom - stackBounds.top);
        boundsOut.set(stackBounds);
        if (fromLeft <= fromTop && fromLeft <= fromRight && fromLeft <= fromBottom) {
            boundsOut.offsetTo(movementBounds.left, stackBounds.top);
        } else if (fromTop <= fromLeft && fromTop <= fromRight && fromTop <= fromBottom) {
            boundsOut.offsetTo(stackBounds.left, movementBounds.top);
        } else if (fromRight < fromLeft && fromRight < fromTop && fromRight < fromBottom) {
            boundsOut.offsetTo(movementBounds.right, stackBounds.top);
        } else {
            boundsOut.offsetTo(stackBounds.left, movementBounds.bottom);
        }
    }

    /**
     * @return the distance between point {@param p} and the given {@param x} and {@param y}.
     */
+13 −6
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ public class PipTouchHandler implements TunerService.Tunable {

    private final PipInputEventReceiver mInputEventReceiver;
    private PipDismissViewController mDismissViewController;
    private PipSnapAlgorithm mSnapAlgorithm;
    private final PipSnapAlgorithm mSnapAlgorithm;
    private PipMotionHelper mMotionHelper;

    private boolean mEnableSwipeToDismiss = true;
@@ -163,6 +163,7 @@ public class PipTouchHandler implements TunerService.Tunable {
        if (mEnableDragToDismiss) {
            mDismissViewController = new PipDismissViewController(context);
        }
        mSnapAlgorithm = new PipSnapAlgorithm(mContext);
        mFlingAnimationUtils = new FlingAnimationUtils(context, 2f);
        mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());

@@ -187,7 +188,8 @@ public class PipTouchHandler implements TunerService.Tunable {
    }

    public void onConfigurationChanged() {
        updateBoundedPinnedStackBounds();
        mSnapAlgorithm.onConfigurationChanged();
        updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */);
    }

    private void handleTouchEvent(MotionEvent ev) {
@@ -203,7 +205,7 @@ public class PipTouchHandler implements TunerService.Tunable {
                    mPinnedStackBoundsAnimator.cancel();
                }

                updateBoundedPinnedStackBounds();
                updateBoundedPinnedStackBounds(true /* updatePinnedStackBounds */);
                initOrResetVelocityTracker();
                mVelocityTracker.addMovement(ev);
                mActivePointerId = ev.getPointerId(0);
@@ -299,6 +301,10 @@ public class PipTouchHandler implements TunerService.Tunable {
                float velocityY = mVelocityTracker.getYVelocity();
                float velocity = PointF.length(velocityX, velocityY);

                // Update the movement bounds again if the state has changed since the user started
                // dragging (ie. when the IME shows)
                updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */);

                if (mIsSwipingToDismiss) {
                    if (Math.abs(velocityX) > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
                        flingToDismiss(velocityX);
@@ -462,14 +468,15 @@ public class PipTouchHandler implements TunerService.Tunable {
    /**
     * Updates the movement bounds of the pinned stack.
     */
    private void updateBoundedPinnedStackBounds() {
    private void updateBoundedPinnedStackBounds(boolean updatePinnedStackBounds) {
        try {
            StackInfo info = mActivityManager.getStackInfo(PINNED_STACK_ID);
            if (info != null) {
                if (updatePinnedStackBounds) {
                    mPinnedStackBounds.set(info.bounds);
                }
                mBoundedPinnedStackBounds.set(mWindowManager.getPictureInPictureMovementBounds(
                        info.displayId));
                mSnapAlgorithm = new PipSnapAlgorithm(mContext);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Could not fetch PIP movement bounds.", e);
+53 −70
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ import android.util.Log;
import android.util.Size;
import android.util.Slog;
import android.util.TypedValue;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;
@@ -68,9 +68,11 @@ class PinnedStackController {
    private boolean mInInteractiveMode;
    private boolean mIsImeShowing;
    private int mImeHeight;
    private final Rect mPreImeShowingBounds = new Rect();
    private ValueAnimator mBoundsAnimator = null;

    // Used to calculate stack bounds across rotations
    private final DisplayInfo mDisplayInfo = new DisplayInfo();

    // The size and position information that describes where the pinned stack will go by default.
    private int mDefaultStackGravity;
    private Size mDefaultStackSize;
@@ -93,7 +95,6 @@ class PinnedStackController {
                    mBoundsAnimator.cancel();
                }
                mInInteractiveMode = inInteractiveMode;
                mPreImeShowingBounds.setEmpty();
            });
        }
    }
@@ -116,6 +117,7 @@ class PinnedStackController {
        mDisplayContent = displayContent;
        mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
        mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
        mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
        reloadResources();
    }

@@ -159,12 +161,8 @@ class PinnedStackController {
     * @return the default bounds to show the PIP when there is no active PIP.
     */
    Rect getDefaultBounds() {
        final Display display = mDisplayContent.getDisplay();
        final Rect insetBounds = new Rect();
        final Point displaySize = new Point();
        display.getRealSize(displaySize);
        mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mTmpInsets);
        getInsetBounds(displaySize, mTmpInsets, insetBounds);
        getInsetBounds(insetBounds);

        final Rect defaultBounds = new Rect();
        Gravity.apply(mDefaultStackGravity, mDefaultStackSize.getWidth(),
@@ -177,12 +175,16 @@ class PinnedStackController {
     *         controller.
     */
    Rect getMovementBounds(Rect stackBounds) {
        final Display display = mDisplayContent.getDisplay();
        return getMovementBounds(stackBounds, true /* adjustForIme */);
    }

    /**
     * @return the movement bounds for the given {@param stackBounds} and the current state of the
     *         controller.
     */
    Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
        final Rect movementBounds = new Rect();
        final Point displaySize = new Point();
        display.getRealSize(displaySize);
        mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mTmpInsets);
        getInsetBounds(displaySize, mTmpInsets, movementBounds);
        getInsetBounds(movementBounds);

        // Adjust the right/bottom to ensure the stack bounds never goes offscreen
        movementBounds.right = Math.max(movementBounds.left, movementBounds.right -
@@ -190,30 +192,34 @@ class PinnedStackController {
        movementBounds.bottom = Math.max(movementBounds.top, movementBounds.bottom -
                stackBounds.height());

        // Adjust the top if the ime is open
        // Apply the movement bounds adjustments based on the current state
        if (adjustForIme) {
            if (mIsImeShowing) {
                movementBounds.bottom -= mImeHeight;
            }

        }
        return movementBounds;
    }

    /**
     * @return the PIP bounds given it's bounds pre-rotation, and post-rotation (with as applied
     * by the display content, which currently transposes the dimensions but keeps each stack in
     * the same physical space on the device).
     * @return the repositioned PIP bounds given it's pre-change bounds, and the new display info.
     */
    Rect getPostRotationBounds(Rect preRotationStackBounds, Rect postRotationStackBounds) {
        // Keep the pinned stack in the same aspect ratio as in the old orientation, but
        // move it into the position in the rotated space, and snap to the closest space
        // in the new orientation.
        final Rect movementBounds = getMovementBounds(preRotationStackBounds);
        final int stackWidth = preRotationStackBounds.width();
        final int stackHeight = preRotationStackBounds.height();
        final int left = postRotationStackBounds.centerX() - (stackWidth / 2);
        final int top = postRotationStackBounds.centerY() - (stackHeight / 2);
        final Rect postRotBounds = new Rect(left, top, left + stackWidth, top + stackHeight);
        return mSnapAlgorithm.findClosestSnapBounds(movementBounds, postRotBounds);
    Rect onDisplayChanged(Rect preChangeStackBounds, DisplayInfo displayInfo) {
        final Rect postChangeStackBounds = new Rect(preChangeStackBounds);
        if (!mDisplayInfo.equals(displayInfo)) {
            // Calculate the snap fraction of the current stack along the old movement bounds, and
            // then update the stack bounds to the same fraction along the rotated movement bounds.
            final Rect preChangeMovementBounds = getMovementBounds(preChangeStackBounds);
            final float snapFraction = mSnapAlgorithm.getSnapFraction(preChangeStackBounds,
                    preChangeMovementBounds);
            mDisplayInfo.copyFrom(displayInfo);

            final Rect postChangeMovementBounds = getMovementBounds(preChangeStackBounds,
                    false /* adjustForIme */);
            mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
                    snapFraction);
        }
        return postChangeStackBounds;
    }

    /**
@@ -228,7 +234,6 @@ class PinnedStackController {
        final Rect stackBounds = new Rect();
        mService.getStackBounds(PINNED_STACK_ID, stackBounds);
        final Rect prevMovementBounds = getMovementBounds(stackBounds);
        final boolean wasAdjustedForIme = mIsImeShowing;
        mIsImeShowing = adjustedForIme;
        mImeHeight = imeHeight;
        if (mInInteractiveMode) {
@@ -238,32 +243,18 @@ class PinnedStackController {
        } else {
            // Otherwise, we can move the PIP to a sane location to ensure that it does not block
            // the user from interacting with the IME
            Rect toBounds;
            if (!wasAdjustedForIme && adjustedForIme) {
                // If we are showing the IME, then store the previous bounds
                mPreImeShowingBounds.set(stackBounds);
                toBounds = adjustBoundsInMovementBounds(stackBounds);
            } else if (wasAdjustedForIme && !adjustedForIme) {
                if (!mPreImeShowingBounds.isEmpty()) {
                    // If we are hiding the IME and the user is not interacting with the PIP, restore
                    // the previous bounds
                    toBounds = mPreImeShowingBounds;
            final Rect movementBounds = getMovementBounds(stackBounds);
            final Rect toBounds = new Rect(stackBounds);
            if (adjustedForIme) {
                // IME visible
                toBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top));
            } else {
                // IME hidden
                if (stackBounds.top == prevMovementBounds.bottom) {
                        // If the PIP is resting on top of the IME, then adjust it with the hiding
                        // of the IME
                        final Rect movementBounds = getMovementBounds(stackBounds);
                        toBounds = new Rect(stackBounds);
                    // If the PIP is resting on top of the IME, then adjust it with the hiding IME
                    toBounds.offsetTo(toBounds.left, movementBounds.bottom);
                    } else {
                        // Otherwise, leave the PIP in place
                        toBounds = stackBounds;
                }
            }
            } else {
                // Otherwise, the IME bounds have changed so we need to adjust the PIP bounds also
                toBounds = adjustBoundsInMovementBounds(stackBounds);
            }
            if (!toBounds.equals(stackBounds)) {
                if (mBoundsAnimator != null) {
                    mBoundsAnimator.cancel();
@@ -274,16 +265,6 @@ class PinnedStackController {
        }
    }

    /**
     * @return the adjusted {@param stackBounds} such that they are in the movement bounds.
     */
    private Rect adjustBoundsInMovementBounds(Rect stackBounds) {
        final Rect movementBounds = getMovementBounds(stackBounds);
        final Rect adjustedBounds = new Rect(stackBounds);
        adjustedBounds.offset(0, Math.min(0, movementBounds.bottom - stackBounds.top));
        return adjustedBounds;
    }

    /**
     * Sends a broadcast that the PIP movement bounds have changed.
     */
@@ -300,10 +281,12 @@ class PinnedStackController {
    /**
     * @return the bounds on the screen that the PIP can be visible in.
     */
    private void getInsetBounds(Point displaySize, Rect insets, Rect outRect) {
        outRect.set(insets.left + mScreenEdgeInsets.x, insets.top + mScreenEdgeInsets.y,
                displaySize.x - insets.right - mScreenEdgeInsets.x,
                displaySize.y - insets.bottom - mScreenEdgeInsets.y);
    private void getInsetBounds(Rect outRect) {
        mService.mPolicy.getStableInsetsLw(mDisplayInfo.rotation, mDisplayInfo.logicalWidth,
                mDisplayInfo.logicalHeight, mTmpInsets);
        outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
                mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
                mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
    }

    /**
+9 −2
Original line number Diff line number Diff line
@@ -387,8 +387,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
        mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
        switch (mStackId) {
            case PINNED_STACK_ID:
                mTmpRect2 = mDisplayContent.getPinnedStackController().getPostRotationBounds(
                        mBounds, mTmpRect2);
                mTmpRect2 = mDisplayContent.getPinnedStackController().onDisplayChanged(mBounds,
                        getDisplayInfo());
                break;
            case DOCKED_STACK_ID:
                repositionDockedStackAfterRotation(mTmpRect2);
@@ -627,6 +627,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
        mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
                "animation background stackId=" + mStackId);

        final Rect oldBounds = new Rect(mBounds);
        Rect bounds = null;
        final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
        if (mStackId == DOCKED_STACK_ID
@@ -651,6 +652,12 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye

        updateDisplayInfo(bounds);

        // Update the pinned stack controller after the display info is updated
        if (mStackId == PINNED_STACK_ID) {
            mDisplayContent.getPinnedStackController().onDisplayChanged(oldBounds,
                    getDisplayInfo());
        }

        super.onDisplayChanged(dc);
    }