Loading core/java/com/android/internal/policy/PipSnapAlgorithm.java +92 −14 Original line number Diff line number Diff line Loading @@ -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(); } Loading Loading @@ -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(); Loading @@ -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}. */ Loading @@ -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}. */ Loading packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +13 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); Loading @@ -187,7 +188,8 @@ public class PipTouchHandler implements TunerService.Tunable { } public void onConfigurationChanged() { updateBoundedPinnedStackBounds(); mSnapAlgorithm.onConfigurationChanged(); updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */); } private void handleTouchEvent(MotionEvent ev) { Loading @@ -203,7 +205,7 @@ public class PipTouchHandler implements TunerService.Tunable { mPinnedStackBoundsAnimator.cancel(); } updateBoundedPinnedStackBounds(); updateBoundedPinnedStackBounds(true /* updatePinnedStackBounds */); initOrResetVelocityTracker(); mVelocityTracker.addMovement(ev); mActivePointerId = ev.getPointerId(0); Loading Loading @@ -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); Loading Loading @@ -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); Loading services/core/java/com/android/server/wm/PinnedStackController.java +53 −70 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -93,7 +95,6 @@ class PinnedStackController { mBoundsAnimator.cancel(); } mInInteractiveMode = inInteractiveMode; mPreImeShowingBounds.setEmpty(); }); } } Loading @@ -116,6 +117,7 @@ class PinnedStackController { mDisplayContent = displayContent; mSnapAlgorithm = new PipSnapAlgorithm(service.mContext); mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler()); mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo()); reloadResources(); } Loading Loading @@ -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(), Loading @@ -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 - Loading @@ -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; } /** Loading @@ -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) { Loading @@ -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(); Loading @@ -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. */ Loading @@ -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); } /** Loading services/core/java/com/android/server/wm/TaskStack.java +9 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 Loading @@ -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); } Loading Loading
core/java/com/android/internal/policy/PipSnapAlgorithm.java +92 −14 Original line number Diff line number Diff line Loading @@ -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(); } Loading Loading @@ -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(); Loading @@ -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}. */ Loading @@ -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}. */ Loading
packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +13 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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()); Loading @@ -187,7 +188,8 @@ public class PipTouchHandler implements TunerService.Tunable { } public void onConfigurationChanged() { updateBoundedPinnedStackBounds(); mSnapAlgorithm.onConfigurationChanged(); updateBoundedPinnedStackBounds(false /* updatePinnedStackBounds */); } private void handleTouchEvent(MotionEvent ev) { Loading @@ -203,7 +205,7 @@ public class PipTouchHandler implements TunerService.Tunable { mPinnedStackBoundsAnimator.cancel(); } updateBoundedPinnedStackBounds(); updateBoundedPinnedStackBounds(true /* updatePinnedStackBounds */); initOrResetVelocityTracker(); mVelocityTracker.addMovement(ev); mActivePointerId = ev.getPointerId(0); Loading Loading @@ -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); Loading Loading @@ -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); Loading
services/core/java/com/android/server/wm/PinnedStackController.java +53 −70 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -93,7 +95,6 @@ class PinnedStackController { mBoundsAnimator.cancel(); } mInInteractiveMode = inInteractiveMode; mPreImeShowingBounds.setEmpty(); }); } } Loading @@ -116,6 +117,7 @@ class PinnedStackController { mDisplayContent = displayContent; mSnapAlgorithm = new PipSnapAlgorithm(service.mContext); mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler()); mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo()); reloadResources(); } Loading Loading @@ -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(), Loading @@ -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 - Loading @@ -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; } /** Loading @@ -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) { Loading @@ -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(); Loading @@ -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. */ Loading @@ -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); } /** Loading
services/core/java/com/android/server/wm/TaskStack.java +9 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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 Loading @@ -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); } Loading