diff options
| author | 2019-12-19 22:19:49 +0000 | |
|---|---|---|
| committer | 2019-12-19 22:19:49 +0000 | |
| commit | 41df8e465cb2a068f2ed443bedef13155d7e781a (patch) | |
| tree | 730f270d71aa67f462bee08110b6d0b8a85c9de5 | |
| parent | 2e673a1a9b8f719275fe1b6edbb4d30f197e4be9 (diff) | |
| parent | ebf1808abcffff462e0c714b1c4ee6e4d051257d (diff) | |
Merge "Move rotation bounds calculation into SysUI"
14 files changed, 218 insertions, 260 deletions
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl index f1d152ba29af..00edb3a29e87 100644 --- a/core/java/android/view/IPinnedStackController.aidl +++ b/core/java/android/view/IPinnedStackController.aidl @@ -45,4 +45,17 @@ interface IPinnedStackController { * {@param animationDuration} suggests the animation duration transitioning to PiP window. */ void startAnimation(in Rect destinationBounds, in Rect sourceRectHint, int animationDuration); + + /** + * Notifies the controller to reset on bounds animation, if there is any. + * This could happen when screen rotation is happening and we need to notify the WM to reset + * any running bounds animation on the pinned stack. + * {@param bounds} here is the final destination bounds. + */ + void resetBoundsAnimation(in Rect bounds); + + /** + * Reports the current default and movement bounds to controller. + */ + void reportBounds(in Rect defaultBounds, in Rect movementBounds); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java index 75e260e7fa70..d1d9b3de7e69 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java @@ -20,11 +20,13 @@ import android.content.Context; import android.content.res.Configuration; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.wm.DisplayWindowController; import java.io.PrintWriter; public interface BasePipManager { - void initialize(Context context, BroadcastDispatcher broadcastDispatcher); + void initialize(Context context, BroadcastDispatcher broadcastDispatcher, + DisplayWindowController displayWindowController); void showPictureInPictureMenu(); default void expandPip() {} default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {} diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java index f10274a952bc..8e34a90e7b51 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java @@ -16,8 +16,14 @@ package com.android.systemui.pip; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.util.TypedValue.COMPLEX_UNIT_DIP; +import static android.view.Surface.ROTATION_0; +import static android.view.Surface.ROTATION_180; +import android.app.ActivityManager; +import android.app.ActivityTaskManager; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -32,10 +38,9 @@ import android.view.DisplayInfo; import android.view.Gravity; import android.view.IPinnedStackController; import android.view.IWindowManager; +import android.view.WindowContainerTransaction; import android.view.WindowManagerGlobal; -import com.android.internal.policy.PipSnapAlgorithm; - import java.io.PrintWriter; /** @@ -154,6 +159,7 @@ public class PipBoundsHandler { */ public void onMinimizedStateChanged(boolean minimized) { mIsMinimized = minimized; + mSnapAlgorithm.setMinimized(minimized); } /** @@ -199,6 +205,7 @@ public class PipBoundsHandler { mReentrySnapFraction = INVALID_SNAP_FRACTION; mReentrySize = null; mLastPipComponentName = null; + mLastDestinationBounds.setEmpty(); } public Rect getLastDestinationBounds() { @@ -235,8 +242,9 @@ public class PipBoundsHandler { */ public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) { final Rect destinationBounds; + final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize); if (bounds == null) { - destinationBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize); + destinationBounds = new Rect(defaultBounds); } else { destinationBounds = new Rect(bounds); } @@ -253,12 +261,85 @@ public class PipBoundsHandler { mPinnedStackController.startAnimation(destinationBounds, sourceRectHint, -1 /* animationDuration */); mLastDestinationBounds.set(destinationBounds); + mPinnedStackController.reportBounds(defaultBounds, + getMovementBounds(defaultBounds)); } catch (RemoteException e) { Log.e(TAG, "Failed to start PiP animation from SysUI", e); } } /** + * Updates the display info, calculating and returning the new stack and movement bounds in the + * new orientation of the device if necessary. + * + * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise. + */ + public boolean onDisplayRotationChanged(Rect outBounds, int displayId, int fromRotation, + int toRotation, WindowContainerTransaction t) { + // Bail early if the event is not sent to current {@link #mDisplayInfo} + if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) { + return false; + } + + // Bail early if the pinned stack is staled. + final ActivityManager.StackInfo pinnedStackInfo; + try { + pinnedStackInfo = ActivityTaskManager.getService() + .getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); + if (pinnedStackInfo == null) return false; + } catch (RemoteException e) { + Log.e(TAG, "Failed to get StackInfo for pinned stack", e); + return false; + } + + // Calculate the snap fraction of the current stack along the old movement bounds + final Rect postChangeStackBounds = new Rect(mLastDestinationBounds); + final float snapFraction = getSnapFraction(postChangeStackBounds); + + // Populate the new {@link #mDisplayInfo}. + // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation, + // therefore, the width/height may require a swap first. + // Moving forward, we should get the new dimensions after rotation from DisplayLayout. + mDisplayInfo.rotation = toRotation; + updateDisplayInfoIfNeeded(); + + // Calculate the stack bounds in the new orientation based on same fraction along the + // rotated movement bounds. + final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds, + false /* adjustForIme */); + mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds, + snapFraction); + if (mIsMinimized) { + applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds); + } + + try { + outBounds.set(postChangeStackBounds); + mLastDestinationBounds.set(outBounds); + mPinnedStackController.resetBoundsAnimation(outBounds); + mPinnedStackController.reportBounds(outBounds, getMovementBounds(outBounds)); + t.setBounds(pinnedStackInfo.stackToken, outBounds); + } catch (RemoteException e) { + Log.e(TAG, "Failed to resize PiP on display rotation", e); + } + return true; + } + + private void updateDisplayInfoIfNeeded() { + final boolean updateNeeded; + if ((mDisplayInfo.rotation == ROTATION_0) || (mDisplayInfo.rotation == ROTATION_180)) { + updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight); + } else { + updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight); + } + if (updateNeeded) { + final int newLogicalHeight = mDisplayInfo.logicalWidth; + mDisplayInfo.logicalWidth = mDisplayInfo.logicalHeight; + mDisplayInfo.logicalHeight = newLogicalHeight; + } + } + + /** * @return whether the given {@param aspectRatio} is valid. */ private boolean isValidPictureInPictureAspectRatio(float aspectRatio) { diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java index e3623c5f332c..f3e707c6408c 100644 --- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.policy; +package com.android.systemui.pip; import android.content.Context; import android.content.res.Configuration; diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java index 583ce67e26d4..29de90bb2824 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java @@ -28,6 +28,7 @@ import android.os.UserManager; import com.android.systemui.SystemUI; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.statusbar.CommandQueue; +import com.android.systemui.wm.DisplayWindowController; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -44,15 +45,17 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks { private final CommandQueue mCommandQueue; private BasePipManager mPipManager; private final BroadcastDispatcher mBroadcastDispatcher; - + private final DisplayWindowController mDisplayWindowController; private boolean mSupportsPip; @Inject public PipUI(Context context, CommandQueue commandQueue, - BroadcastDispatcher broadcastDispatcher) { + BroadcastDispatcher broadcastDispatcher, + DisplayWindowController displayWindowController) { super(context); mBroadcastDispatcher = broadcastDispatcher; mCommandQueue = commandQueue; + mDisplayWindowController = displayWindowController; } @Override @@ -72,7 +75,7 @@ public class PipUI extends SystemUI implements CommandQueue.Callbacks { mPipManager = pm.hasSystemFeature(FEATURE_LEANBACK_ONLY) ? com.android.systemui.pip.tv.PipManager.getInstance() : com.android.systemui.pip.phone.PipManager.getInstance(); - mPipManager.initialize(mContext, mBroadcastDispatcher); + mPipManager.initialize(mContext, mBroadcastDispatcher, mDisplayWindowController); mCommandQueue.addCallback(this); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index a4707cfb4948..0a89017ff05d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -34,6 +34,7 @@ import android.util.Log; import android.util.Pair; import android.view.DisplayInfo; import android.view.IPinnedStackController; +import android.view.WindowContainerTransaction; import com.android.systemui.Dependency; import com.android.systemui.UiOffloadThread; @@ -45,6 +46,7 @@ import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.WindowManagerWrapper; +import com.android.systemui.wm.DisplayWindowController; import java.io.PrintWriter; @@ -75,9 +77,22 @@ public class PipManager implements BasePipManager { private PipAppOpsListener mAppOpsListener; /** + * Handler for display rotation changes. + */ + private final DisplayWindowController.OnDisplayWindowRotationController mRotationController = ( + int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> { + final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds, + displayId, fromRotation, toRotation, t); + if (changed) { + updateMovementBounds(mTmpNormalBounds, false /* fromImeAdjustment */, + false /* fromShelfAdjustment */); + } + }; + + /** * Handler for system task stack changes. */ - TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { + private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { @Override public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { mTouchHandler.onActivityPinned(); @@ -214,7 +229,8 @@ public class PipManager implements BasePipManager { /** * Initializes {@link PipManager}. */ - public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) { + public void initialize(Context context, BroadcastDispatcher broadcastDispatcher, + DisplayWindowController displayWindowController) { mContext = context; mActivityManager = ActivityManager.getService(); mActivityTaskManager = ActivityTaskManager.getService(); @@ -235,6 +251,7 @@ public class PipManager implements BasePipManager { mMenuController, mInputConsumerController, mPipBoundsHandler); mAppOpsListener = new PipAppOpsListener(context, mActivityManager, mTouchHandler.getMotionHelper()); + displayWindowController.addRotationController(mRotationController); // If SystemUI restart, and it already existed a pinned stack, // register the pip input consumer to ensure touch can send to it. diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index fa6047755619..6afa0bfcbdb6 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -46,7 +46,7 @@ import android.view.animation.Interpolator; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.internal.os.SomeArgs; -import com.android.internal.policy.PipSnapAlgorithm; +import com.android.systemui.pip.PipSnapAlgorithm; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.FlingAnimationUtils; diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 2347a476d145..95e3444f4779 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -46,9 +46,9 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityWindowInfo; import com.android.internal.os.logging.MetricsLoggerWrapper; -import com.android.internal.policy.PipSnapAlgorithm; import com.android.systemui.R; import com.android.systemui.pip.PipBoundsHandler; +import com.android.systemui.pip.PipSnapAlgorithm; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.statusbar.FlingAnimationUtils; diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index 195fca85a314..696db683a7d0 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -55,6 +55,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.WindowManagerWrapper; +import com.android.systemui.wm.DisplayWindowController; import java.util.ArrayList; import java.util.List; @@ -228,7 +229,8 @@ public class PipManager implements BasePipManager { /** * Initializes {@link PipManager}. */ - public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) { + public void initialize(Context context, BroadcastDispatcher broadcastDispatcher, + DisplayWindowController displayWindowController) { if (mInitialized) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java index ae82115ca37e..aa56ffb18554 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java @@ -101,10 +101,11 @@ public class DisplayWindowController { } DisplayRecord record = new DisplayRecord(); record.mDisplayId = displayId; - Display display = getDisplay(displayId); - record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext - : mContext.createDisplayContext(display); - record.mDisplayLayout = new DisplayLayout(record.mContext, display); + // TODO(b/146566787): disabled for MultiDisplayActivityLaunchTests + // Display display = getDisplay(displayId); + // record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext + // : mContext.createDisplayContext(display); + // record.mDisplayLayout = new DisplayLayout(record.mContext, display); mDisplays.put(displayId, record); for (int i = 0; i < mDisplayChangedListeners.size(); ++i) { mDisplayChangedListeners.get(i).onDisplayAdded(displayId); @@ -123,13 +124,14 @@ public class DisplayWindowController { + " display."); return; } - Display display = getDisplay(displayId); - Context perDisplayContext = mContext; - if (displayId != Display.DEFAULT_DISPLAY) { - perDisplayContext = mContext.createDisplayContext(display); - } - dr.mContext = perDisplayContext.createConfigurationContext(newConfig); - dr.mDisplayLayout = new DisplayLayout(dr.mContext, display); + // TODO(b/146566787): disabled for MultiDisplaySystemDecorationTests + // Display display = getDisplay(displayId); + // Context perDisplayContext = mContext; + // if (displayId != Display.DEFAULT_DISPLAY) { + // perDisplayContext = mContext.createDisplayContext(display); + // } + // dr.mContext = perDisplayContext.createConfigurationContext(newConfig); + // dr.mDisplayLayout = new DisplayLayout(dr.mContext, display); for (int i = 0; i < mDisplayChangedListeners.size(); ++i) { mDisplayChangedListeners.get(i).onDisplayConfigurationChanged( displayId, newConfig); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index a741d45011d2..62dd7bb85df5 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -821,10 +821,7 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn // Update bounds if applicable boolean hasNewOverrideBounds = false; // Use override windowing mode to prevent extra bounds changes if inheriting the mode. - if (overrideWindowingMode == WINDOWING_MODE_PINNED) { - // Pinned calculation already includes rotation - hasNewOverrideBounds = calculatePinnedBoundsForConfigChange(newBounds); - } else if (!matchParentBounds()) { + if ((overrideWindowingMode != WINDOWING_MODE_PINNED) && !matchParentBounds()) { // If the parent (display) has rotated, rotate our bounds to best-fit where their // bounds were on the pre-rotated display. final int newRotation = getWindowConfiguration().getRotation(); @@ -882,9 +879,6 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn null /* tempTaskBounds */, null /* tempTaskInsetBounds */, null /* tempOtherTaskBounds */, null /* tempOtherTaskInsetBounds */, PRESERVE_WINDOWS, true /* deferResume */); - } else { - resize(new Rect(newBounds), null /* tempTaskBounds */, - null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, true /* deferResume */); } } if (prevIsAlwaysOnTop != isAlwaysOnTop()) { @@ -4089,45 +4083,27 @@ class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAn } /** - * Updates the passed-in {@code inOutBounds} based on the current state of the - * pinned controller. This gets run *after* the override configuration is updated, so it's - * safe to rely on the controller's state in here (though eventually this dependence should - * be removed). - * - * This does NOT modify this TaskStack's configuration. However, it does, for the time-being, - * update pinned controller state. + * Reset the current animation running on {@link #mBoundsAnimationTarget}. * - * @param inOutBounds the bounds to update (both input and output). - * @return true if bounds were updated to some non-empty value. + * @param destinationBounds the final destination bounds */ - boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) { - boolean animating = false; - if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) { - animating = true; - getFinalAnimationBounds(mTmpRect2); - } else { - mTmpRect2.set(inOutBounds); - } - boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged( - mTmpRect2, mTmpRect3); - if (updated) { - inOutBounds.set(mTmpRect3); - - // The final boundary is updated while there is an existing boundary animation. Let's - // cancel this animation to prevent the obsolete animation overwritten updated bounds. - if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) { - final DisplayContent displayContent = getDisplayContent(); - displayContent.mBoundsAnimationController.getHandler().post(() -> - displayContent.mBoundsAnimationController.cancel(this)); - } - // Once we've set the bounds based on the rotation of the old bounds in the new - // orientation, clear the animation target bounds since they are obsolete, and - // cancel any currently running animations - mBoundsAnimationTarget.setEmpty(); - mBoundsAnimationSourceHintBounds.setEmpty(); - mCancelCurrentBoundsAnimation = true; - } - return updated; + void resetCurrentBoundsAnimation(Rect destinationBounds) { + boolean animating = (mBoundsAnimatingRequested || mBoundsAnimating) + && !mBoundsAnimationTarget.isEmpty(); + + // The final boundary is updated while there is an existing boundary animation. Let's + // cancel this animation to prevent the obsolete animation overwritten updated bounds. + if (animating && !destinationBounds.equals(mBoundsAnimationTarget)) { + final BoundsAnimationController controller = + getDisplayContent().mBoundsAnimationController; + controller.getHandler().post(() -> controller.cancel(this)); + } + // Once we've set the bounds based on the rotation of the old bounds in the new + // orientation, clear the animation target bounds since they are obsolete, and + // cancel any currently running animations + mBoundsAnimationTarget.setEmpty(); + mBoundsAnimationSourceHintBounds.setEmpty(); + mCancelCurrentBoundsAnimation = true; } /** diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index e02456e81822..45b4818add11 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3302,6 +3302,23 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Configuration c = new Configuration(container.getRequestedOverrideConfiguration()); c.setTo(change.getConfiguration(), configMask, windowMask); container.onRequestedOverrideConfigurationChanged(c); + // TODO(b/145675353): remove the following once we could apply new bounds to the + // pinned stack together with its children. + resizePinnedStackIfNeeded(container, configMask, windowMask, c); + } + + private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask, + int windowMask, Configuration config) { + if ((container instanceof ActivityStack) + && ((configMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) + && ((windowMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)) { + final ActivityStack stack = (ActivityStack) container; + if (stack.inPinnedWindowingMode()) { + stack.resize(config.windowConfiguration.getBounds(), + null /* tempTaskBounds */, null /* tempTaskInsetBounds */, + PRESERVE_WINDOWS, true /* deferResume */); + } + } } @Override diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java index 5dc88b37e445..9b464c2d1b96 100644 --- a/services/core/java/com/android/server/wm/BoundsAnimationController.java +++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java @@ -185,6 +185,10 @@ public class BoundsAnimationController { resume(); }; + // If this animator is explicitly cancelled when it's in paused state, we should not + // attempt to resume the animation. Use this flag to avoid such behavior. + private boolean mIsCancelled; + BoundsAnimator(BoundsAnimationTarget target, @AnimationType int animationType, Rect from, Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState, @SchedulePipModeChangedState int prevShedulePipModeChangedState, @@ -221,6 +225,7 @@ public class BoundsAnimationController { if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget + " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState); + mIsCancelled = false; mFinishAnimationAfterTransition = false; mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth, mFrom.top + mFrozenTaskHeight); @@ -293,7 +298,7 @@ public class BoundsAnimationController { public void resume() { if (DEBUG) Slog.d(TAG, "resume:"); mHandler.removeCallbacks(mResumeRunnable); - super.resume(); + if (!mIsCancelled) super.resume(); } @Override @@ -376,6 +381,7 @@ public class BoundsAnimationController { @Override public void onAnimationCancel(Animator animation) { + mIsCancelled = true; // Always skip the final resize when the animation is canceled mSkipFinalResize = true; mMoveToFullscreen = false; diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index a8e7aea64883..b4f75e545729 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -16,38 +16,29 @@ package com.android.server.wm; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.util.TypedValue.COMPLEX_UNIT_DIP; import static com.android.server.wm.PinnedStackControllerProto.DEFAULT_BOUNDS; import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import android.annotation.NonNull; import android.app.RemoteAction; import android.content.ComponentName; import android.content.pm.ParceledListSlice; import android.content.res.Resources; -import android.graphics.Point; import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.util.DisplayMetrics; import android.util.Log; -import android.util.Size; import android.util.Slog; -import android.util.TypedValue; import android.util.proto.ProtoOutputStream; import android.view.DisplayInfo; -import android.view.Gravity; import android.view.IPinnedStackController; import android.view.IPinnedStackListener; -import com.android.internal.policy.PipSnapAlgorithm; -import com.android.internal.util.Preconditions; import com.android.server.UiThread; import java.io.PrintWriter; @@ -74,7 +65,6 @@ class PinnedStackController { private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM; - private static final float INVALID_SNAP_FRACTION = -1f; private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final Handler mHandler = UiThread.getHandler(); @@ -84,7 +74,6 @@ class PinnedStackController { new PinnedStackListenerDeathHandler(); private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback(); - private final PipSnapAlgorithm mSnapAlgorithm; // States that affect how the PIP can be manipulated private boolean mIsMinimized; @@ -97,13 +86,9 @@ class PinnedStackController { // Used to calculate stack bounds across rotations private final DisplayInfo mDisplayInfo = new DisplayInfo(); - private final Rect mStableInsets = new Rect(); // The size and position information that describes where the pinned stack will go by default. - private int mDefaultMinSize; - private int mDefaultStackGravity; private float mDefaultAspectRatio; - private Point mScreenEdgeInsets; // The aspect ratio bounds of the PIP. private float mMinAspectRatio; @@ -111,10 +96,11 @@ class PinnedStackController { // Temp vars for calculation private final DisplayMetrics mTmpMetrics = new DisplayMetrics(); - private final Rect mTmpInsets = new Rect(); - private final Rect mTmpRect = new Rect(); - private final Point mTmpDisplaySize = new Point(); + // TODO(b/141200935): remove this when we have default/movement bounds tests in SysUI. + // Keep record of the default and movement bounds + private final Rect mLastReportedDefaultBounds = new Rect(); + private final Rect mLastReportedMovementBounds = new Rect(); /** * The callback object passed to listeners for them to notify the controller of state changes. @@ -125,7 +111,6 @@ class PinnedStackController { public void setIsMinimized(final boolean isMinimized) { mHandler.post(() -> { mIsMinimized = isMinimized; - mSnapAlgorithm.setMinimized(isMinimized); }); } @@ -145,6 +130,27 @@ class PinnedStackController { sourceRectHint, animationDuration, true /* fromFullscreen */); } } + + @Override + public void resetBoundsAnimation(Rect bounds) { + synchronized (mService.mGlobalLock) { + if (mDisplayContent.hasPinnedStack()) { + final ActivityStack pinnedStack = mDisplayContent.getTopStackInWindowingMode( + WINDOWING_MODE_PINNED); + if (pinnedStack != null) { + pinnedStack.resetCurrentBoundsAnimation(bounds); + } + } + } + } + + @Override + public void reportBounds(Rect defaultBounds, Rect movementBounds) { + synchronized (mService.mGlobalLock) { + mLastReportedDefaultBounds.set(defaultBounds); + mLastReportedMovementBounds.set(movementBounds); + } + } } /** @@ -165,7 +171,6 @@ class PinnedStackController { PinnedStackController(WindowManagerService service, DisplayContent displayContent) { mService = service; mDisplayContent = displayContent; - mSnapAlgorithm = new PipSnapAlgorithm(service.mContext); mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo()); reloadResources(); // Initialize the aspect ratio to the default aspect ratio. Don't do this in reload @@ -183,21 +188,9 @@ class PinnedStackController { */ private void reloadResources() { final Resources res = mService.mContext.getResources(); - mDefaultMinSize = res.getDimensionPixelSize( - com.android.internal.R.dimen.default_minimal_size_pip_resizable_task); mDefaultAspectRatio = res.getFloat( com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio); - final String screenEdgeInsetsDpString = res.getString( - com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets); - final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty() - ? Size.parseSize(screenEdgeInsetsDpString) - : null; - mDefaultStackGravity = res.getInteger( - com.android.internal.R.integer.config_defaultPictureInPictureGravity); mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics); - mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point() - : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics), - dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics)); mMinAspectRatio = res.getFloat( com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); mMaxAspectRatio = res.getFloat( @@ -215,7 +208,7 @@ class PinnedStackController { notifyDisplayInfoChanged(mDisplayInfo); notifyImeVisibilityChanged(mIsImeShowing, mImeHeight); // The movement bounds notification needs to be sent before the minimized state, since - // SystemUI may use the bounds to retore the minimized position + // SystemUI may use the bounds to restore the minimized position notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */); notifyActionsChanged(mActions); @@ -257,30 +250,6 @@ class PinnedStackController { } } - /** - * @return the default bounds to show the PIP, if a {@param snapFraction} is provided, then it - * will apply the default bounds to the provided snap fraction. - */ - private Rect getDefaultBounds(float snapFraction) { - synchronized (mService.mGlobalLock) { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - - final Rect defaultBounds = new Rect(); - final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio, - mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); - if (snapFraction != INVALID_SNAP_FRACTION) { - defaultBounds.set(0, 0, size.getWidth(), size.getHeight()); - final Rect movementBounds = getMovementBounds(defaultBounds); - mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction); - } else { - Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds, - 0, mIsImeShowing ? mImeHeight : 0, defaultBounds); - } - return defaultBounds; - } - } - private void setDisplayInfo(DisplayInfo displayInfo) { mDisplayInfo.copyFrom(displayInfo); notifyDisplayInfoChanged(mDisplayInfo); @@ -300,51 +269,6 @@ class PinnedStackController { } /** - * Updates the display info, calculating and returning the new stack and movement bounds in the - * new orientation of the device if necessary. - */ - boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) { - synchronized (mService.mGlobalLock) { - final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); - if (isSameDimensionAndRotation(mDisplayInfo, displayInfo)) { - // No dimension/rotation change, 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 - setDisplayInfo(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 float snapFraction = getSnapFraction(postChangeStackBounds); - - setDisplayInfo(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 */, - false /* fromShelfAdjustment */); - - outBounds.set(postChangeStackBounds); - return true; - } - } - - /** * Sets the Ime state and height. */ void setAdjustedForIme(boolean adjustedForIme, int imeHeight) { @@ -400,15 +324,6 @@ class PinnedStackController { notifyPrepareAnimation(sourceRectHint, aspectRatio, stackBounds); } - private boolean isSameDimensionAndRotation(@NonNull DisplayInfo display1, - @NonNull DisplayInfo display2) { - Preconditions.checkNotNull(display1); - Preconditions.checkNotNull(display2); - return ((display1.rotation == display2.rotation) - && (display1.logicalWidth == display2.logicalWidth) - && (display1.logicalHeight == display2.logicalHeight)); - } - /** * Notifies listeners that the PIP needs to be adjusted for the IME. */ @@ -504,86 +419,11 @@ class PinnedStackController { } } - /** - * @return the bounds on the screen that the PIP can be visible in. - */ - private void getInsetBounds(Rect outRect) { - synchronized (mService.mGlobalLock) { - mDisplayContent.getDisplayPolicy().getStableInsetsLw(mDisplayInfo.rotation, - mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight, - mDisplayInfo.displayCutout, mTmpInsets); - outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y, - mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x, - mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y); - } - } - - /** - * @return the movement bounds for the given {@param stackBounds} and the current state of the - * controller. - */ - private Rect getMovementBounds(Rect stackBounds) { - synchronized (mService.mGlobalLock) { - return getMovementBounds(stackBounds, true /* adjustForIme */); - } - } - - /** - * @return the movement bounds for the given {@param stackBounds} and the current state of the - * controller. - */ - private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) { - synchronized (mService.mGlobalLock) { - final Rect movementBounds = new Rect(); - getInsetBounds(movementBounds); - - // Apply the movement bounds adjustments based on the current state. - // Note that shelf offset does not affect the movement bounds here - // since it's been taken care of in system UI. - 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) { - synchronized (mService.mGlobalLock) { - mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); - mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets); - mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize, - mStableInsets); - } - } - - /** - * @return the default snap fraction to apply instead of the default gravity when calculating - * the default stack bounds when first entering PiP. - */ - private float getSnapFraction(Rect stackBounds) { - return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds)); - } - - /** - * @return the pixels for a given dp value. - */ - private int dpToPx(float dpValue, DisplayMetrics dm) { - return (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, dpValue, dm); - } - void dump(String prefix, PrintWriter pw) { pw.println(prefix + "PinnedStackController"); - pw.print(prefix + " defaultBounds="); - getDefaultBounds(INVALID_SNAP_FRACTION).printShortString(pw); - pw.println(); - pw.println(prefix + " mDefaultMinSize=" + mDefaultMinSize); - pw.println(prefix + " mDefaultStackGravity=" + mDefaultStackGravity); + pw.println(prefix + " mLastReportedDefaultBounds=" + mLastReportedDefaultBounds); + pw.println(prefix + " mLastReportedMovementBounds=" + mLastReportedMovementBounds); pw.println(prefix + " mDefaultAspectRatio=" + mDefaultAspectRatio); - mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect); - pw.print(prefix + " movementBounds="); getMovementBounds(mTmpRect).printShortString(pw); - pw.println(); pw.println(prefix + " mIsImeShowing=" + mIsImeShowing); pw.println(prefix + " mImeHeight=" + mImeHeight); pw.println(prefix + " mIsMinimized=" + mIsMinimized); @@ -606,9 +446,8 @@ class PinnedStackController { void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); - getDefaultBounds(INVALID_SNAP_FRACTION).dumpDebug(proto, DEFAULT_BOUNDS); - mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect); - getMovementBounds(mTmpRect).dumpDebug(proto, MOVEMENT_BOUNDS); + mLastReportedDefaultBounds.dumpDebug(proto, DEFAULT_BOUNDS); + mLastReportedMovementBounds.dumpDebug(proto, MOVEMENT_BOUNDS); proto.end(token); } } |