Merge "Tightening up rotation behavior for PIP (3/3)" into oc-dev
am: c2627353c4
Change-Id: I867999bac435926e9f54fb33e489ea3f44d1dad0
This commit is contained in:
@@ -28,4 +28,9 @@ interface IPinnedStackController {
|
||||
* Notifies the controller that the PiP is currently minimized.
|
||||
*/
|
||||
oneway void setIsMinimized(boolean isMinimized);
|
||||
|
||||
/**
|
||||
* @return what WM considers to be the current device rotation.
|
||||
*/
|
||||
int getDisplayRotation();
|
||||
}
|
||||
|
||||
@@ -41,9 +41,13 @@ oneway interface IPinnedStackListener {
|
||||
* current state with the aspect ratio applied. The {@param animatingBounds} are provided
|
||||
* to indicate the current target bounds of the pinned stack (the final bounds if animating,
|
||||
* the current bounds if not), which may be helpful in calculating dependent animation bounds.
|
||||
*
|
||||
* The {@param displayRotation} is provided so that the client can verify when making certain
|
||||
* calls that it will not provide stale information based on an old display rotation (ie. if
|
||||
* the WM has changed in the mean time but the client has not received onMovementBoundsChanged).
|
||||
*/
|
||||
void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, in Rect animatingBounds,
|
||||
boolean fromImeAdjustement);
|
||||
boolean fromImeAdjustement, int displayRotation);
|
||||
|
||||
/**
|
||||
* Called when window manager decides to adjust the pinned stack bounds because of the IME, or
|
||||
|
||||
@@ -143,10 +143,10 @@ public class PipManager implements BasePipManager {
|
||||
|
||||
@Override
|
||||
public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
|
||||
Rect animatingBounds, boolean fromImeAdjustement) {
|
||||
Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) {
|
||||
mHandler.post(() -> {
|
||||
mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds,
|
||||
fromImeAdjustement);
|
||||
fromImeAdjustement, displayRotation);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -220,6 +220,13 @@ public class PipMenuActivity extends Activity {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
cancelDelayedFinish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
@@ -316,7 +316,8 @@ public class PipMotionHelper {
|
||||
* Animates the PiP from the expanded state to the normal state after the menu is hidden.
|
||||
*/
|
||||
void animateToUnexpandedState(Rect normalBounds, float savedSnapFraction,
|
||||
Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized) {
|
||||
Rect normalMovementBounds, Rect currentMovementBounds, boolean minimized,
|
||||
boolean immediate) {
|
||||
if (savedSnapFraction < 0f) {
|
||||
// If there are no saved snap fractions, then just use the current bounds
|
||||
savedSnapFraction = mSnapAlgorithm.getSnapFraction(new Rect(mBounds),
|
||||
@@ -326,7 +327,11 @@ public class PipMotionHelper {
|
||||
if (minimized) {
|
||||
normalBounds = getClosestMinimizedBounds(normalBounds, normalMovementBounds);
|
||||
}
|
||||
resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION);
|
||||
if (immediate) {
|
||||
movePip(normalBounds);
|
||||
} else {
|
||||
resizeAndAnimatePipUnchecked(normalBounds, SHRINK_STACK_FROM_MENU_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,6 +89,11 @@ public class PipTouchHandler implements TunerService.Tunable {
|
||||
private Rect mExpandedMovementBounds = new Rect();
|
||||
private int mExpandedShortestEdgeSize;
|
||||
|
||||
// Used to workaround an issue where the WM rotation happens before we are notified, allowing
|
||||
// us to send stale bounds
|
||||
private int mDeferResizeToNormalBoundsUntilRotation = -1;
|
||||
private int mDisplayRotation;
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
private Runnable mShowDismissAffordance = new Runnable() {
|
||||
@Override
|
||||
@@ -250,7 +255,7 @@ public class PipTouchHandler implements TunerService.Tunable {
|
||||
}
|
||||
|
||||
public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds,
|
||||
boolean fromImeAdjustement) {
|
||||
boolean fromImeAdjustement, int displayRotation) {
|
||||
// Re-calculate the expanded bounds
|
||||
mNormalBounds = normalBounds;
|
||||
Rect normalMovementBounds = new Rect();
|
||||
@@ -304,7 +309,17 @@ public class PipTouchHandler implements TunerService.Tunable {
|
||||
// above
|
||||
mNormalMovementBounds = normalMovementBounds;
|
||||
mExpandedMovementBounds = expandedMovementBounds;
|
||||
mDisplayRotation = displayRotation;
|
||||
updateMovementBounds(mMenuState);
|
||||
|
||||
// If we have a deferred resize, apply it now
|
||||
if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {
|
||||
mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
|
||||
mNormalMovementBounds, mMovementBounds, mIsMinimized,
|
||||
true /* immediate */);
|
||||
mSavedSnapFraction = -1f;
|
||||
mDeferResizeToNormalBoundsUntilRotation = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void onRegistrationChanged(boolean isRegistered) {
|
||||
@@ -474,11 +489,34 @@ public class PipTouchHandler implements TunerService.Tunable {
|
||||
// Try and restore the PiP to the closest edge, using the saved snap fraction
|
||||
// if possible
|
||||
if (resize) {
|
||||
Rect normalBounds = new Rect(mNormalBounds);
|
||||
mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
|
||||
mNormalMovementBounds, mMovementBounds, mIsMinimized);
|
||||
// This is a very special case: when the menu is expanded and visible, navigating to
|
||||
// another activity can trigger auto-enter PiP, and if the revealed activity has a
|
||||
// forced rotation set, then the controller will get updated with the new rotation
|
||||
// of the display. However, at the same time, SystemUI will try to hide the menu by
|
||||
// creating an animation to the normal bounds which are now stale. In such a case
|
||||
// we defer the animation to the normal bounds until after the next
|
||||
// onMovementBoundsChanged() call to get the bounds in the new orientation
|
||||
if (mDeferResizeToNormalBoundsUntilRotation == -1) {
|
||||
try {
|
||||
int displayRotation = mPinnedStackController.getDisplayRotation();
|
||||
if (mDisplayRotation != displayRotation) {
|
||||
mDeferResizeToNormalBoundsUntilRotation = displayRotation;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not get display rotation from controller");
|
||||
}
|
||||
}
|
||||
|
||||
if (mDeferResizeToNormalBoundsUntilRotation == -1) {
|
||||
Rect normalBounds = new Rect(mNormalBounds);
|
||||
mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
|
||||
mNormalMovementBounds, mMovementBounds, mIsMinimized,
|
||||
false /* immediate */);
|
||||
mSavedSnapFraction = -1f;
|
||||
}
|
||||
} else {
|
||||
mSavedSnapFraction = -1f;
|
||||
}
|
||||
mSavedSnapFraction = -1f;
|
||||
}
|
||||
mMenuState = menuState;
|
||||
updateMovementBounds(menuState);
|
||||
|
||||
@@ -178,7 +178,7 @@ public class PipManager implements BasePipManager {
|
||||
|
||||
@Override
|
||||
public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
|
||||
Rect animatingBounds, boolean fromImeAdjustement) {
|
||||
Rect animatingBounds, boolean fromImeAdjustement, int displayRotation) {
|
||||
mHandler.post(() -> {
|
||||
mDefaultPipBounds.set(normalBounds);
|
||||
});
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.app.RemoteAction;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -123,6 +122,13 @@ class PinnedStackController {
|
||||
mSnapAlgorithm.setMinimized(isMinimized);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplayRotation() {
|
||||
synchronized (mService.mWindowMap) {
|
||||
return mDisplayInfo.rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,22 +227,26 @@ class PinnedStackController {
|
||||
* @return the size of the PIP based on the given {@param aspectRatio}.
|
||||
*/
|
||||
Size getSize(float aspectRatio) {
|
||||
return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize,
|
||||
mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
|
||||
synchronized (mService.mWindowMap) {
|
||||
return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize,
|
||||
mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default bounds to show the PIP when there is no active PIP.
|
||||
*/
|
||||
Rect getDefaultBounds() {
|
||||
final Rect insetBounds = new Rect();
|
||||
getInsetBounds(insetBounds);
|
||||
synchronized (mService.mWindowMap) {
|
||||
final Rect insetBounds = new Rect();
|
||||
getInsetBounds(insetBounds);
|
||||
|
||||
final Rect defaultBounds = new Rect();
|
||||
final Size size = getSize(mDefaultAspectRatio);
|
||||
Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
|
||||
0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
|
||||
return defaultBounds;
|
||||
final Rect defaultBounds = new Rect();
|
||||
final Size size = getSize(mDefaultAspectRatio);
|
||||
Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
|
||||
0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
|
||||
return defaultBounds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,42 +264,44 @@ class PinnedStackController {
|
||||
* new orientation of the device if necessary.
|
||||
*/
|
||||
boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
|
||||
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
|
||||
if (mDisplayInfo.equals(displayInfo)) {
|
||||
// We are already in the right orientation, ignore
|
||||
outBounds.setEmpty();
|
||||
return false;
|
||||
} else if (targetBounds.isEmpty()) {
|
||||
// The stack is null, we are just initializing the stack, so just store the display info
|
||||
// and ignore
|
||||
synchronized (mService.mWindowMap) {
|
||||
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
|
||||
if (mDisplayInfo.equals(displayInfo)) {
|
||||
// We are already in the right orientation, ignore
|
||||
outBounds.setEmpty();
|
||||
return false;
|
||||
} else if (targetBounds.isEmpty()) {
|
||||
// The stack is null, we are just initializing the stack, so just store the display
|
||||
// info and ignore
|
||||
mDisplayInfo.copyFrom(displayInfo);
|
||||
outBounds.setEmpty();
|
||||
return false;
|
||||
}
|
||||
|
||||
mTmpRect.set(targetBounds);
|
||||
final Rect postChangeStackBounds = mTmpRect;
|
||||
|
||||
// Calculate the snap fraction of the current stack along the old movement bounds
|
||||
final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds);
|
||||
final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds,
|
||||
preChangeMovementBounds);
|
||||
mDisplayInfo.copyFrom(displayInfo);
|
||||
outBounds.setEmpty();
|
||||
return false;
|
||||
|
||||
// Calculate the stack bounds in the new orientation to the same same fraction along the
|
||||
// rotated movement bounds.
|
||||
final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
|
||||
false /* adjustForIme */);
|
||||
mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
|
||||
snapFraction);
|
||||
if (mIsMinimized) {
|
||||
applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
|
||||
}
|
||||
|
||||
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
|
||||
|
||||
outBounds.set(postChangeStackBounds);
|
||||
return true;
|
||||
}
|
||||
|
||||
mTmpRect.set(targetBounds);
|
||||
final Rect postChangeStackBounds = mTmpRect;
|
||||
|
||||
// Calculate the snap fraction of the current stack along the old movement bounds
|
||||
final Rect preChangeMovementBounds = getMovementBounds(postChangeStackBounds);
|
||||
final float snapFraction = mSnapAlgorithm.getSnapFraction(postChangeStackBounds,
|
||||
preChangeMovementBounds);
|
||||
mDisplayInfo.copyFrom(displayInfo);
|
||||
|
||||
// Calculate the stack bounds in the new orientation to the same same fraction along the
|
||||
// rotated movement bounds.
|
||||
final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
|
||||
false /* adjustForIme */);
|
||||
mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
|
||||
snapFraction);
|
||||
if (mIsMinimized) {
|
||||
applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
|
||||
}
|
||||
|
||||
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
|
||||
|
||||
outBounds.set(postChangeStackBounds);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,25 +390,27 @@ class PinnedStackController {
|
||||
* Notifies listeners that the PIP movement bounds have changed.
|
||||
*/
|
||||
private void notifyMovementBoundsChanged(boolean fromImeAdjustement) {
|
||||
if (mPinnedStackListener != null) {
|
||||
try {
|
||||
final Rect insetBounds = new Rect();
|
||||
getInsetBounds(insetBounds);
|
||||
final Rect normalBounds = getDefaultBounds();
|
||||
if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
|
||||
transformBoundsToAspectRatio(normalBounds, mAspectRatio);
|
||||
synchronized (mService.mWindowMap) {
|
||||
if (mPinnedStackListener != null) {
|
||||
try {
|
||||
final Rect insetBounds = new Rect();
|
||||
getInsetBounds(insetBounds);
|
||||
final Rect normalBounds = getDefaultBounds();
|
||||
if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
|
||||
transformBoundsToAspectRatio(normalBounds, mAspectRatio);
|
||||
}
|
||||
final Rect animatingBounds = mTmpAnimatingBoundsRect;
|
||||
final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
|
||||
if (pinnedStack != null) {
|
||||
pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
|
||||
} else {
|
||||
animatingBounds.set(normalBounds);
|
||||
}
|
||||
mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
|
||||
animatingBounds, fromImeAdjustement, mDisplayInfo.rotation);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG_WM, "Error delivering actions changed event.", e);
|
||||
}
|
||||
final Rect animatingBounds = mTmpAnimatingBoundsRect;
|
||||
final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
|
||||
if (pinnedStack != null) {
|
||||
pinnedStack.getAnimationOrCurrentBounds(animatingBounds);
|
||||
} else {
|
||||
animatingBounds.set(normalBounds);
|
||||
}
|
||||
mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds,
|
||||
animatingBounds, fromImeAdjustement);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG_WM, "Error delivering actions changed event.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,11 +419,13 @@ class PinnedStackController {
|
||||
* @return the bounds on the screen that the PIP can be visible in.
|
||||
*/
|
||||
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);
|
||||
synchronized (mService.mWindowMap) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,7 +433,9 @@ class PinnedStackController {
|
||||
* controller.
|
||||
*/
|
||||
private Rect getMovementBounds(Rect stackBounds) {
|
||||
return getMovementBounds(stackBounds, true /* adjustForIme */);
|
||||
synchronized (mService.mWindowMap) {
|
||||
return getMovementBounds(stackBounds, true /* adjustForIme */);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -425,23 +443,27 @@ class PinnedStackController {
|
||||
* controller.
|
||||
*/
|
||||
private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
|
||||
final Rect movementBounds = new Rect();
|
||||
getInsetBounds(movementBounds);
|
||||
synchronized (mService.mWindowMap) {
|
||||
final Rect movementBounds = new Rect();
|
||||
getInsetBounds(movementBounds);
|
||||
|
||||
// Apply the movement bounds adjustments based on the current state
|
||||
mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
|
||||
(adjustForIme && mIsImeShowing) ? mImeHeight : 0);
|
||||
return movementBounds;
|
||||
// Apply the movement bounds adjustments based on the current state
|
||||
mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
|
||||
(adjustForIme && mIsImeShowing) ? mImeHeight : 0);
|
||||
return movementBounds;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the minimized offsets to the given stack bounds.
|
||||
*/
|
||||
private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
|
||||
mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
|
||||
mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
|
||||
mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
|
||||
mStableInsets);
|
||||
synchronized (mService.mWindowMap) {
|
||||
mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
|
||||
mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
|
||||
mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
|
||||
mStableInsets);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user