diff options
17 files changed, 307 insertions, 379 deletions
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl index f1d152ba29af..d2dcb568ef6c 100644 --- a/core/java/android/view/IPinnedStackController.aidl +++ b/core/java/android/view/IPinnedStackController.aidl @@ -16,8 +16,6 @@ package android.view; -import android.graphics.Rect; - /** * An interface to the PinnedStackController to update it of state changes, and to query * information based on the current state. @@ -32,17 +30,15 @@ interface IPinnedStackController { oneway void setIsMinimized(boolean isMinimized); /** - * @return what WM considers to be the current device rotation. + * Notifies the controller of the current min edge size, this is needed to allow the system to + * properly calculate the aspect ratio of the expanded PIP. The given {@param minEdgeSize} is + * always bounded to be larger than the default minEdgeSize, so the caller can call this method + * with 0 to reset to the default size. */ - int getDisplayRotation(); + oneway void setMinEdgeSize(int minEdgeSize); /** - * Notifies the controller to actually start the PiP animation. - * The bounds would be calculated based on the last save reentry fraction internally. - * {@param destinationBounds} is the stack bounds of the final PiP window - * and {@param sourceRectHint} is the source bounds hint used when entering picture-in-picture, - * expect the same bound passed via IPinnedStackListener#onPrepareAnimation. - * {@param animationDuration} suggests the animation duration transitioning to PiP window. + * @return what WM considers to be the current device rotation. */ - void startAnimation(in Rect destinationBounds, in Rect sourceRectHint, int animationDuration); + int getDisplayRotation(); } diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedStackListener.aidl index 806d81e39cca..2da353b1f0ee 100644 --- a/core/java/android/view/IPinnedStackListener.aidl +++ b/core/java/android/view/IPinnedStackListener.aidl @@ -16,10 +16,8 @@ package android.view; -import android.content.ComponentName; import android.content.pm.ParceledListSlice; import android.graphics.Rect; -import android.view.DisplayInfo; import android.view.IPinnedStackController; /** @@ -38,13 +36,18 @@ oneway interface IPinnedStackListener { /** * Called when the window manager has detected a change that would cause the movement bounds * to be changed (ie. after configuration change, aspect ratio change, etc). It then provides - * the components that allow the listener to calculate the movement bounds itself. - * 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 components that allow the listener to calculate the movement bounds itself. The + * {@param normalBounds} are also the default bounds that the PiP would be entered in its + * 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 animatingBounds, boolean fromImeAdjustment, - boolean fromShelfAdjustment); + void onMovementBoundsChanged(in Rect insetBounds, in Rect normalBounds, in Rect animatingBounds, + boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation); /** * Called when window manager decides to adjust the pinned stack bounds because of the IME, or @@ -73,47 +76,4 @@ oneway interface IPinnedStackListener { * is first registered to allow the listener to synchronized its state with the controller. */ void onActionsChanged(in ParceledListSlice actions); - - /** - * Called by the window manager to notify the listener to save the reentry fraction, - * typically when an Activity leaves PiP (picture-in-picture) mode to fullscreen. - * {@param componentName} represents the application component of PiP window - * while {@param bounds} is the current PiP bounds used to calculate the - * reentry snap fraction. - */ - void onSaveReentrySnapFraction(in ComponentName componentName, in Rect bounds); - - /** - * Called by the window manager to notify the listener to reset saved reentry fraction, - * typically when an Activity enters PiP (picture-in-picture) mode from fullscreen. - * {@param componentName} represents the application component of PiP window. - */ - void onResetReentrySnapFraction(in ComponentName componentName); - - /** - * Called when the window manager has detected change on DisplayInfo, or - * when the listener is first registered to allow the listener to synchronized its state with - * the controller. - */ - void onDisplayInfoChanged(in DisplayInfo displayInfo); - - /** - * Called by the window manager at the beginning of a configuration update cascade - * since the metrics from these resources are used for bounds calculations. - */ - void onConfigurationChanged(); - - /** - * Called by the window manager when the aspect ratio is reset. - */ - void onAspectRatioChanged(float aspectRatio); - - /** - * Called by the window manager to notify the listener to prepare for PiP animation. - * Internally, the target bounds would be calculated from the given {@param aspectRatio} - * and {@param bounds}, the saved reentry snap fraction also contributes. - * Caller would wait for a IPinnedStackController#startAnimation callback to actually - * start the animation, see details in IPinnedStackController. - */ - void onPrepareAnimation(in Rect sourceRectHint, float aspectRatio, in Rect bounds); } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java index 2797042ac160..3ae2df5b97bf 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/PinnedStackListenerForwarder.java @@ -16,10 +16,9 @@ package com.android.systemui.shared.system; -import android.content.ComponentName; import android.content.pm.ParceledListSlice; import android.graphics.Rect; -import android.view.DisplayInfo; +import android.os.RemoteException; import android.view.IPinnedStackController; import android.view.IPinnedStackListener; @@ -33,132 +32,62 @@ import java.util.List; * previously set listener. */ public class PinnedStackListenerForwarder extends IPinnedStackListener.Stub { - private List<PinnedStackListener> mListeners = new ArrayList<>(); + private List<IPinnedStackListener> mListeners = new ArrayList<>(); /** Adds a listener to receive updates from the WindowManagerService. */ - public void addListener(PinnedStackListener listener) { + public void addListener(IPinnedStackListener listener) { mListeners.add(listener); } /** Removes a listener so it will no longer receive updates from the WindowManagerService. */ - public void removeListener(PinnedStackListener listener) { + public void removeListener(IPinnedStackListener listener) { mListeners.remove(listener); } @Override - public void onListenerRegistered(IPinnedStackController controller) { - for (PinnedStackListener listener : mListeners) { + public void onListenerRegistered(IPinnedStackController controller) throws RemoteException { + for (IPinnedStackListener listener : mListeners) { listener.onListenerRegistered(controller); } } @Override - public void onMovementBoundsChanged(Rect animatingBounds, boolean fromImeAdjustment, - boolean fromShelfAdjustment) { - for (PinnedStackListener listener : mListeners) { - listener.onMovementBoundsChanged(animatingBounds, fromImeAdjustment, - fromShelfAdjustment); + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds, + boolean fromImeAdjustment, boolean fromShelfAdjustment, int displayRotation) + throws RemoteException { + for (IPinnedStackListener listener : mListeners) { + listener.onMovementBoundsChanged( + insetBounds, normalBounds, animatingBounds, + fromImeAdjustment, fromShelfAdjustment, displayRotation); } } @Override - public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { - for (PinnedStackListener listener : mListeners) { + public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) throws RemoteException { + for (IPinnedStackListener listener : mListeners) { listener.onImeVisibilityChanged(imeVisible, imeHeight); } } @Override - public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) { - for (PinnedStackListener listener : mListeners) { + public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) + throws RemoteException { + for (IPinnedStackListener listener : mListeners) { listener.onShelfVisibilityChanged(shelfVisible, shelfHeight); } } @Override - public void onMinimizedStateChanged(boolean isMinimized) { - for (PinnedStackListener listener : mListeners) { + public void onMinimizedStateChanged(boolean isMinimized) throws RemoteException { + for (IPinnedStackListener listener : mListeners) { listener.onMinimizedStateChanged(isMinimized); } } @Override - public void onActionsChanged(ParceledListSlice actions) { - for (PinnedStackListener listener : mListeners) { + public void onActionsChanged(ParceledListSlice actions) throws RemoteException { + for (IPinnedStackListener listener : mListeners) { listener.onActionsChanged(actions); } } - - @Override - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) { - for (PinnedStackListener listener : mListeners) { - listener.onSaveReentrySnapFraction(componentName, bounds); - } - } - - @Override - public void onResetReentrySnapFraction(ComponentName componentName) { - for (PinnedStackListener listener : mListeners) { - listener.onResetReentrySnapFraction(componentName); - } - } - - @Override - public void onDisplayInfoChanged(DisplayInfo displayInfo) { - for (PinnedStackListener listener : mListeners) { - listener.onDisplayInfoChanged(displayInfo); - } - } - - @Override - public void onConfigurationChanged() { - for (PinnedStackListener listener : mListeners) { - listener.onConfigurationChanged(); - } - } - - @Override - public void onAspectRatioChanged(float aspectRatio) { - for (PinnedStackListener listener : mListeners) { - listener.onAspectRatioChanged(aspectRatio); - } - } - - @Override - public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) { - for (PinnedStackListener listener : mListeners) { - listener.onPrepareAnimation(sourceRectHint, aspectRatio, bounds); - } - } - - /** - * A counterpart of {@link IPinnedStackListener} with empty implementations. - * Subclasses can ignore those methods they do not intend to take action upon. - */ - public static class PinnedStackListener { - public void onListenerRegistered(IPinnedStackController controller) {} - - public void onMovementBoundsChanged(Rect animatingBounds, boolean fromImeAdjustment, - boolean fromShelfAdjustment) {} - - public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {} - - public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {} - - public void onMinimizedStateChanged(boolean isMinimized) {} - - public void onActionsChanged(ParceledListSlice actions) {} - - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) {} - - public void onResetReentrySnapFraction(ComponentName componentName) {} - - public void onDisplayInfoChanged(DisplayInfo displayInfo) {} - - public void onConfigurationChanged() {} - - public void onAspectRatioChanged(float aspectRatio) {} - - public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) {} - } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java index 9f1a1fafeec6..794c30a7c7c1 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java @@ -27,12 +27,12 @@ import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; import android.util.Log; +import android.view.IPinnedStackListener; import android.view.WindowManager; import android.view.WindowManagerGlobal; import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture; import com.android.systemui.shared.recents.view.RecentsTransition; -import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener; public class WindowManagerWrapper { @@ -212,7 +212,7 @@ public class WindowManagerWrapper { * Adds a pinned stack listener, which will receive updates from the window manager service * along with any other pinned stack listeners that were added via this method. */ - public void addPinnedStackListener(PinnedStackListener listener) throws RemoteException { + public void addPinnedStackListener(IPinnedStackListener listener) throws RemoteException { mPinnedStackListenerForwarder.addListener(listener); WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener( DEFAULT_DISPLAY, mPinnedStackListenerForwarder); @@ -221,7 +221,7 @@ public class WindowManagerWrapper { /** * Removes a pinned stack listener. */ - public void removePinnedStackListener(PinnedStackListener listener) { + public void removePinnedStackListener(IPinnedStackListener listener) { mPinnedStackListenerForwarder.removeListener(listener); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 43576a4e21ef..67fc3e32883f 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -48,6 +48,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.pm.ActivityInfo; +import android.content.pm.ParceledListSlice; import android.content.res.Configuration; import android.graphics.Rect; import android.os.RemoteException; @@ -60,6 +61,8 @@ import android.util.Log; import android.util.Pair; import android.util.SparseSetArray; import android.view.Display; +import android.view.IPinnedStackController; +import android.view.IPinnedStackListener; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -73,7 +76,6 @@ import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; -import com.android.systemui.shared.system.PinnedStackListenerForwarder; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -991,12 +993,32 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } /** PinnedStackListener that dispatches IME visibility updates to the stack. */ - private class BubblesImeListener extends PinnedStackListenerForwarder.PinnedStackListener { + private class BubblesImeListener extends IPinnedStackListener.Stub { + + @Override + public void onListenerRegistered(IPinnedStackController controller) throws RemoteException { + } + + @Override + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, + Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment, + int displayRotation) throws RemoteException {} + @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { if (mStackView != null && mStackView.getBubbleCount() > 0) { mStackView.post(() -> mStackView.onImeVisibilityChanged(imeVisible, imeHeight)); } } + + @Override + public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) + throws RemoteException {} + + @Override + public void onMinimizedStateChanged(boolean isMinimized) throws RemoteException {} + + @Override + public void onActionsChanged(ParceledListSlice actions) throws RemoteException {} } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java index 6795bff6409a..30be7754cffc 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java @@ -18,7 +18,6 @@ package com.android.systemui.pip; import static android.util.TypedValue.COMPLEX_UNIT_DIP; -import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; import android.graphics.Point; @@ -47,6 +46,9 @@ public class PipBoundsHandler { private static final String TAG = PipBoundsHandler.class.getSimpleName(); private static final float INVALID_SNAP_FRACTION = -1f; + // System.identityHashCode guarantees zero for null object. + private static final int INVALID_SYSTEM_IDENTITY_TOKEN = 0; + private final Context mContext; private final IWindowManager mWindowManager; private final PipSnapAlgorithm mSnapAlgorithm; @@ -56,7 +58,7 @@ public class PipBoundsHandler { private final Point mTmpDisplaySize = new Point(); private IPinnedStackController mPinnedStackController; - private ComponentName mLastPipComponentName; + private int mLastPipToken; private float mReentrySnapFraction = INVALID_SNAP_FRACTION; private float mDefaultAspectRatio; @@ -78,11 +80,8 @@ public class PipBoundsHandler { mContext = context; mSnapAlgorithm = new PipSnapAlgorithm(context); mWindowManager = WindowManagerGlobal.getWindowManagerService(); - reloadResources(); - // Initialize the aspect ratio to the default aspect ratio. Don't do this in reload - // resources as it would clobber mAspectRatio when entering PiP from fullscreen which - // triggers a configuration change and the resources to be reloaded. mAspectRatio = mDefaultAspectRatio; + reloadResources(); } /** @@ -162,27 +161,27 @@ public class PipBoundsHandler { } /** - * Responds to IPinnedStackListener on saving reentry snap fraction - * for a given {@link ComponentName}. + * Responds to IPinnedStackListener on saving reentry snap fraction for a given token. + * Token should be generated via {@link System#identityHashCode(Object)} */ - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) { - mReentrySnapFraction = getSnapFraction(bounds); - mLastPipComponentName = componentName; + public void onSaveReentrySnapFraction(int token, Rect stackBounds) { + mReentrySnapFraction = getSnapFraction(stackBounds); + mLastPipToken = token; } /** - * Responds to IPinnedStackListener on resetting reentry snap fraction - * for a given {@link ComponentName}. + * Responds to IPinnedStackListener on resetting reentry snap fraction for a given token. + * Token should be generated via {@link System#identityHashCode(Object)} */ - public void onResetReentrySnapFraction(ComponentName componentName) { - if (componentName.equals(mLastPipComponentName)) { + public void onResetReentrySnapFraction(int token) { + if (mLastPipToken == token) { onResetReentrySnapFractionUnchecked(); } } private void onResetReentrySnapFractionUnchecked() { mReentrySnapFraction = INVALID_SNAP_FRACTION; - mLastPipComponentName = null; + mLastPipToken = INVALID_SYSTEM_IDENTITY_TOKEN; } /** @@ -213,28 +212,24 @@ public class PipBoundsHandler { /** * Responds to IPinnedStackListener on preparing the pinned stack animation. */ - public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) { - final Rect destinationBounds; - if (bounds == null) { - destinationBounds = getDefaultBounds(mReentrySnapFraction); + public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect stackBounds) { + final Rect targetStackBounds; + if (stackBounds == null) { + targetStackBounds = getDefaultBounds(mReentrySnapFraction); } else { - destinationBounds = new Rect(bounds); + targetStackBounds = new Rect(); + targetStackBounds.set(stackBounds); } if (isValidPictureInPictureAspectRatio(aspectRatio)) { - transformBoundsToAspectRatio(destinationBounds, aspectRatio, - false /* useCurrentMinEdgeSize */); + transformBoundsToAspectRatio(targetStackBounds, aspectRatio, + true /* useCurrentMinEdgeSize */); } - if (destinationBounds.equals(bounds)) { + if (targetStackBounds.equals(stackBounds)) { return; } mAspectRatio = aspectRatio; onResetReentrySnapFractionUnchecked(); - try { - mPinnedStackController.startAnimation(destinationBounds, sourceRectHint, - -1 /* animationDuration */); - } catch (RemoteException e) { - Log.e(TAG, "Failed to start PiP animation from SysUI", e); - } + // TODO: callback Window Manager on starting animation with calculated bounds } /** @@ -363,7 +358,6 @@ public class PipBoundsHandler { public void dump(PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; pw.println(prefix + TAG); - pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName); pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction); pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo); pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio); 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 8dfae32a1939..3be3422a36ad 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -32,16 +32,14 @@ import android.os.Handler; import android.os.RemoteException; import android.util.Log; import android.util.Pair; -import android.view.DisplayInfo; import android.view.IPinnedStackController; +import android.view.IPinnedStackListener; import com.android.systemui.Dependency; import com.android.systemui.UiOffloadThread; import com.android.systemui.pip.BasePipManager; -import com.android.systemui.pip.PipBoundsHandler; import com.android.systemui.shared.system.ActivityManagerWrapper; 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; @@ -60,12 +58,8 @@ public class PipManager implements BasePipManager { private IActivityTaskManager mActivityTaskManager; private Handler mHandler = new Handler(); - private final PinnedStackListener mPinnedStackListener = new PipManagerPinnedStackListener(); - private final DisplayInfo mTmpDisplayInfo = new DisplayInfo(); - private final Rect mTmpInsetBounds = new Rect(); - private final Rect mTmpNormalBounds = new Rect(); + private final PinnedStackListener mPinnedStackListener = new PinnedStackListener(); - private PipBoundsHandler mPipBoundsHandler; private InputConsumerController mInputConsumerController; private PipMenuActivityController mMenuController; private PipMediaController mMediaController; @@ -125,11 +119,11 @@ public class PipManager implements BasePipManager { /** * Handler for messages from the PIP controller. */ - private class PipManagerPinnedStackListener extends PinnedStackListener { + private class PinnedStackListener extends IPinnedStackListener.Stub { + @Override public void onListenerRegistered(IPinnedStackController controller) { mHandler.post(() -> { - mPipBoundsHandler.setPinnedStackController(controller); mTouchHandler.setPinnedStackController(controller); }); } @@ -137,7 +131,6 @@ public class PipManager implements BasePipManager { @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { mHandler.post(() -> { - mPipBoundsHandler.onImeVisibilityChanged(imeVisible, imeHeight); mTouchHandler.onImeVisibilityChanged(imeVisible, imeHeight); }); } @@ -145,66 +138,31 @@ public class PipManager implements BasePipManager { @Override public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) { mHandler.post(() -> { - mPipBoundsHandler.onShelfVisibilityChanged(shelfVisible, shelfHeight); - mTouchHandler.onShelfVisibilityChanged(shelfVisible, shelfHeight); + mTouchHandler.onShelfVisibilityChanged(shelfVisible, shelfHeight); }); } @Override public void onMinimizedStateChanged(boolean isMinimized) { mHandler.post(() -> { - mPipBoundsHandler.onMinimizedStateChanged(isMinimized); mTouchHandler.setMinimizedState(isMinimized, true /* fromController */); }); } @Override - public void onMovementBoundsChanged(Rect animatingBounds, boolean fromImeAdjustment, - boolean fromShelfAdjustment) { + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, + Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment, + int displayRotation) { mHandler.post(() -> { - // Populate the inset / normal bounds and DisplayInfo from mPipBoundsHandler first. - mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, - animatingBounds, mTmpDisplayInfo); - mTouchHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, - animatingBounds, fromImeAdjustment, fromShelfAdjustment, - mTmpDisplayInfo.rotation); + mTouchHandler.onMovementBoundsChanged(insetBounds, normalBounds, animatingBounds, + fromImeAdjustment, fromShelfAdjustment, displayRotation); }); } @Override public void onActionsChanged(ParceledListSlice actions) { - mHandler.post(() -> mMenuController.setAppActions(actions)); - } - - @Override - public void onSaveReentrySnapFraction(ComponentName componentName, Rect bounds) { - mHandler.post(() -> mPipBoundsHandler.onSaveReentrySnapFraction(componentName, bounds)); - } - - @Override - public void onResetReentrySnapFraction(ComponentName componentName) { - mHandler.post(() -> mPipBoundsHandler.onResetReentrySnapFraction(componentName)); - } - - @Override - public void onDisplayInfoChanged(DisplayInfo displayInfo) { - mHandler.post(() -> mPipBoundsHandler.onDisplayInfoChanged(displayInfo)); - } - - @Override - public void onConfigurationChanged() { - mHandler.post(() -> mPipBoundsHandler.onConfigurationChanged()); - } - - @Override - public void onAspectRatioChanged(float aspectRatio) { - mHandler.post(() -> mPipBoundsHandler.onAspectRatioChanged(aspectRatio)); - } - - @Override - public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) { mHandler.post(() -> { - mPipBoundsHandler.onPrepareAnimation(sourceRectHint, aspectRatio, bounds); + mMenuController.setAppActions(actions); }); } } @@ -226,13 +184,12 @@ public class PipManager implements BasePipManager { } ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); - mPipBoundsHandler = new PipBoundsHandler(context); mInputConsumerController = InputConsumerController.getPipInputConsumer(); mMediaController = new PipMediaController(context, mActivityManager); mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController, mInputConsumerController); mTouchHandler = new PipTouchHandler(context, mActivityManager, mActivityTaskManager, - mMenuController, mInputConsumerController, mPipBoundsHandler); + mMenuController, mInputConsumerController); mAppOpsListener = new PipAppOpsListener(context, mActivityManager, mTouchHandler.getMotionHelper()); @@ -295,6 +252,5 @@ public class PipManager implements BasePipManager { mInputConsumerController.dump(pw, innerPrefix); mMenuController.dump(pw, innerPrefix); mTouchHandler.dump(pw, innerPrefix); - mPipBoundsHandler.dump(pw, innerPrefix); } } 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 1f36d97ce308..30cf412671bc 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -48,7 +48,6 @@ 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.shared.system.InputConsumerController; import com.android.systemui.statusbar.FlingAnimationUtils; @@ -76,7 +75,6 @@ public class PipTouchHandler { private final IActivityTaskManager mActivityTaskManager; private final ViewConfiguration mViewConfig; private final PipMenuListener mMenuListener = new PipMenuListener(); - private final PipBoundsHandler mPipBoundsHandler; private IPinnedStackController mPinnedStackController; private final PipMenuActivityController mMenuController; @@ -180,8 +178,7 @@ public class PipTouchHandler { public PipTouchHandler(Context context, IActivityManager activityManager, IActivityTaskManager activityTaskManager, PipMenuActivityController menuController, - InputConsumerController inputConsumerController, - PipBoundsHandler pipBoundsHandler) { + InputConsumerController inputConsumerController) { // Initialize the Pip input consumer mContext = context; @@ -214,8 +211,6 @@ public class PipTouchHandler { inputConsumerController.setInputListener(this::handleTouchEvent); inputConsumerController.setRegistrationListener(this::onRegistrationChanged); onRegistrationChanged(inputConsumerController.isRegistered()); - - mPipBoundsHandler = pipBoundsHandler; } public void setTouchEnabled(boolean enabled) { @@ -792,8 +787,14 @@ public class PipTouchHandler { mMovementBounds = isMenuExpanded ? mExpandedMovementBounds : mNormalMovementBounds; - mPipBoundsHandler.setMinEdgeSize( - isMenuExpanded ? mExpandedShortestEdgeSize : 0); + try { + if (mPinnedStackController != null) { + mPinnedStackController.setMinEdgeSize( + isMenuExpanded ? mExpandedShortestEdgeSize : 0); + } + } catch (RemoteException e) { + Log.e(TAG, "Could not set minimized state", e); + } } /** 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 81d6973efb2a..918af4f0cd4c 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -19,10 +19,13 @@ package com.android.systemui.pip.tv; import static android.app.ActivityTaskManager.INVALID_STACK_ID; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.view.Display.DEFAULT_DISPLAY; +import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.StackInfo; import android.app.ActivityTaskManager; +import android.app.IActivityManager; import android.app.IActivityTaskManager; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -43,15 +46,16 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.Pair; -import android.view.DisplayInfo; +import android.view.IPinnedStackController; +import android.view.IPinnedStackListener; +import android.view.IWindowManager; +import android.view.WindowManagerGlobal; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.UiOffloadThread; import com.android.systemui.pip.BasePipManager; -import com.android.systemui.pip.PipBoundsHandler; 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; @@ -107,8 +111,9 @@ public class PipManager implements BasePipManager { private int mSuspendPipResizingReason; private Context mContext; - private PipBoundsHandler mPipBoundsHandler; + private IActivityManager mActivityManager; private IActivityTaskManager mActivityTaskManager; + private IWindowManager mWindowManager; private MediaSessionManager mMediaSessionManager; private int mState = STATE_NO_PIP; private int mResumeResizePinnedStackRunnableState = STATE_NO_PIP; @@ -130,16 +135,11 @@ public class PipManager implements BasePipManager { private PipNotification mPipNotification; private ParceledListSlice mCustomActions; - // Used to calculate the movement bounds - private final DisplayInfo mTmpDisplayInfo = new DisplayInfo(); - private final Rect mTmpInsetBounds = new Rect(); - private final Rect mTmpNormalBounds = new Rect(); - // Keeps track of the IME visibility to adjust the PiP when the IME is visible private boolean mImeVisible; private int mImeHeightAdjustment; - private final PinnedStackListener mPinnedStackListener = new PipManagerPinnedStackListener(); + private final PinnedStackListener mPinnedStackListener = new PinnedStackListener(); private final Runnable mResizePinnedStackRunnable = new Runnable() { @Override @@ -181,7 +181,11 @@ public class PipManager implements BasePipManager { /** * Handler for messages from the PIP controller. */ - private class PipManagerPinnedStackListener extends PinnedStackListener { + private class PinnedStackListener extends IPinnedStackListener.Stub { + + @Override + public void onListenerRegistered(IPinnedStackController controller) {} + @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { if (mState == STATE_PIP) { @@ -201,13 +205,17 @@ public class PipManager implements BasePipManager { } @Override - public void onMovementBoundsChanged(Rect animatingBounds, boolean fromImeAdjustment, - boolean fromShelfAdjustment) { + public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {} + + @Override + public void onMinimizedStateChanged(boolean isMinimized) {} + + @Override + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, + Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment, + int displayRotation) { mHandler.post(() -> { - // Populate the inset / normal bounds and DisplayInfo from mPipBoundsHandler first. - mPipBoundsHandler.onMovementBoundsChanged(mTmpInsetBounds, mTmpNormalBounds, - animatingBounds, mTmpDisplayInfo); - mDefaultPipBounds.set(animatingBounds); + mDefaultPipBounds.set(normalBounds); }); } @@ -233,8 +241,10 @@ public class PipManager implements BasePipManager { } mInitialized = true; mContext = context; - mPipBoundsHandler = new PipBoundsHandler(context); + + mActivityManager = ActivityManager.getService(); mActivityTaskManager = ActivityTaskManager.getService(); + mWindowManager = WindowManagerGlobal.getWindowManagerService(); ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED); @@ -281,7 +291,7 @@ public class PipManager implements BasePipManager { (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE); try { - WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener); + mWindowManager.registerPinnedStackListener(DEFAULT_DISPLAY, mPinnedStackListener); } catch (RemoteException e) { Log.e(TAG, "Failed to register pinned stack listener", e); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java index 4cd3ad27ab34..575b5597b657 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import static android.view.Display.INVALID_DISPLAY; import android.content.Context; +import android.content.pm.ParceledListSlice; import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.Point; @@ -35,6 +36,8 @@ import android.util.Log; import android.util.MathUtils; import android.util.StatsLog; import android.view.Gravity; +import android.view.IPinnedStackController; +import android.view.IPinnedStackListener; import android.view.ISystemGestureExclusionListener; import android.view.InputChannel; import android.view.InputDevice; @@ -54,7 +57,6 @@ import com.android.systemui.R; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.model.SysUiState; import com.android.systemui.recents.OverviewProxyService; -import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -70,13 +72,35 @@ public class EdgeBackGestureHandler implements DisplayListener { private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt( "gestures.back_timeout", 250); - private final PinnedStackListener mImeChangedListener = new PinnedStackListener() { + private final IPinnedStackListener.Stub mImeChangedListener = new IPinnedStackListener.Stub() { + @Override + public void onListenerRegistered(IPinnedStackController controller) { + } + @Override public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) { // No need to thread jump, assignments are atomic mImeHeight = imeVisible ? imeHeight : 0; // TODO: Probably cancel any existing gesture } + + @Override + public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) { + } + + @Override + public void onMinimizedStateChanged(boolean isMinimized) { + } + + @Override + public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, + Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment, + int displayRotation) { + } + + @Override + public void onActionsChanged(ParceledListSlice actions) { + } }; private ISystemGestureExclusionListener mGestureExclusionListener = diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 8bb37bbdfc87..50200a7cf7bc 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -4940,6 +4940,12 @@ class ActivityStack extends ConfigurationContainer { } } + + Rect getDefaultPictureInPictureBounds(float aspectRatio) { + if (getTaskStack() == null) return null; + return getTaskStack().getPictureInPictureBounds(aspectRatio, null /* currentStackBounds */); + } + void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, boolean fromFullscreen) { if (!inPinnedWindowingMode()) return; diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 71f02e8a8569..ffd9021989b4 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -1021,7 +1021,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this); mAppStopped = true; // Reset the last saved PiP snap fraction on app stop. - mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(mActivityComponent); + mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this); destroySurfaces(); // Remove any starting window that was added for this app if they are still around. removeStartingWindow(); @@ -1705,7 +1705,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree return; } - if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED + if (prevWinMode != WINDOWING_MODE_UNDEFINED && winMode == WINDOWING_MODE_PINNED) { + // Entering PiP from fullscreen, reset the snap fraction + mDisplayContent.mPinnedStackControllerLocked.resetReentrySnapFraction(this); + } else if (prevWinMode == WINDOWING_MODE_PINNED && winMode != WINDOWING_MODE_UNDEFINED && !isHidden()) { // Leaving PiP to fullscreen, save the snap fraction based on the pre-animation bounds // for the next re-entry into PiP (assuming the activity is not hidden or destroyed) @@ -1723,8 +1726,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree stackBounds = mTmpRect; pinnedStack.getBounds(stackBounds); } - mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction( - mActivityComponent, stackBounds); + mDisplayContent.mPinnedStackControllerLocked.saveReentrySnapFraction(this, + stackBounds); } } else if (shouldStartChangeTransition(prevWinMode, winMode)) { initializeChangeTransition(mTmpPrevBounds); diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 8e57fec6ba46..ef0049b068f4 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -27,7 +27,6 @@ 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; @@ -51,6 +50,7 @@ import com.android.internal.util.Preconditions; import com.android.server.UiThread; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -74,7 +74,7 @@ class PinnedStackController { private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM; - private static final float INVALID_SNAP_FRACTION = -1f; + public static final float INVALID_SNAP_FRACTION = -1f; private final WindowManagerService mService; private final DisplayContent mDisplayContent; private final Handler mHandler = UiThread.getHandler(); @@ -106,6 +106,9 @@ class PinnedStackController { private int mDefaultStackGravity; private float mDefaultAspectRatio; private Point mScreenEdgeInsets; + private int mCurrentMinSize; + private float mReentrySnapFraction = INVALID_SNAP_FRACTION; + private WeakReference<AppWindowToken> mLastPipActivity = null; // The aspect ratio bounds of the PIP. private float mMinAspectRatio; @@ -115,6 +118,7 @@ class PinnedStackController { private final DisplayMetrics mTmpMetrics = new DisplayMetrics(); private final Rect mTmpInsets = new Rect(); private final Rect mTmpRect = new Rect(); + private final Rect mTmpAnimatingBoundsRect = new Rect(); private final Point mTmpDisplaySize = new Point(); @@ -132,19 +136,16 @@ class PinnedStackController { } @Override - public int getDisplayRotation() { - synchronized (mService.mGlobalLock) { - return mDisplayInfo.rotation; - } + public void setMinEdgeSize(int minEdgeSize) { + mHandler.post(() -> { + mCurrentMinSize = Math.max(mDefaultMinSize, minEdgeSize); + }); } @Override - public void startAnimation(Rect destinationBounds, Rect sourceRectHint, - int animationDuration) { + public int getDisplayRotation() { synchronized (mService.mGlobalLock) { - final TaskStack pinnedStack = mDisplayContent.getPinnedStack(); - pinnedStack.animateResizePinnedStack(destinationBounds, - sourceRectHint, animationDuration, true /* fromFullscreen */); + return mDisplayInfo.rotation; } } } @@ -187,6 +188,7 @@ class PinnedStackController { final Resources res = mService.mContext.getResources(); mDefaultMinSize = res.getDimensionPixelSize( com.android.internal.R.dimen.default_minimal_size_pip_resizable_task); + mCurrentMinSize = mDefaultMinSize; mDefaultAspectRatio = res.getFloat( com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio); final String screenEdgeInsetsDpString = res.getString( @@ -214,7 +216,6 @@ class PinnedStackController { listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0); listener.onListenerRegistered(mCallbacks); mPinnedStackListener = listener; - notifyDisplayInfoChanged(mDisplayInfo); notifyImeVisibilityChanged(mIsImeShowing, mImeHeight); notifyShelfVisibilityChanged(mIsShelfShowing, mShelfHeight); // The movement bounds notification needs to be sent before the minimized state, since @@ -237,34 +238,58 @@ class PinnedStackController { } /** - * Saves the current snap fraction for re-entry of the current activity into PiP. + * Returns the current bounds (or the default bounds if there are no current bounds) with the + * specified aspect ratio. */ - void saveReentrySnapFraction(final ComponentName componentName, final Rect stackBounds) { - if (mPinnedStackListener == null) return; - try { - mPinnedStackListener.onSaveReentrySnapFraction(componentName, stackBounds); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering save reentry fraction event.", e); + Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio, + boolean useCurrentMinEdgeSize) { + // Save the snap fraction, calculate the aspect ratio based on screen size + final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds, + getMovementBounds(stackBounds)); + + final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize; + final Size size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize, + mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); + final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f); + final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f); + stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight()); + mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction); + if (mIsMinimized) { + applyMinimizedOffset(stackBounds, getMovementBounds(stackBounds)); } + return stackBounds; + } + + /** + * Saves the current snap fraction for re-entry of the current activity into PiP. + */ + void saveReentrySnapFraction(final AppWindowToken token, final Rect stackBounds) { + mReentrySnapFraction = getSnapFraction(stackBounds); + mLastPipActivity = new WeakReference<>(token); } /** * Resets the last saved snap fraction so that the default bounds will be returned. */ - void resetReentrySnapFraction(ComponentName componentName) { - if (mPinnedStackListener == null) return; - try { - mPinnedStackListener.onResetReentrySnapFraction(componentName); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering reset reentry fraction event.", e); + void resetReentrySnapFraction(AppWindowToken token) { + if (mLastPipActivity != null && mLastPipActivity.get() == token) { + mReentrySnapFraction = INVALID_SNAP_FRACTION; + mLastPipActivity = null; } } /** + * @return the default bounds to show the PIP when there is no active PIP. + */ + Rect getDefaultOrLastSavedBounds() { + return getDefaultBounds(mReentrySnapFraction); + } + + /** * @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) { + Rect getDefaultBounds(float snapFraction) { synchronized (mService.mGlobalLock) { final Rect insetBounds = new Rect(); getInsetBounds(insetBounds); @@ -286,18 +311,13 @@ class PinnedStackController { } } - private void setDisplayInfo(DisplayInfo displayInfo) { - mDisplayInfo.copyFrom(displayInfo); - notifyDisplayInfoChanged(mDisplayInfo); - } - /** * In the case where the display rotation is changed but there is no stack, we can't depend on * onTaskStackBoundsChanged() to be called. But we still should update our known display info * with the new state so that we can update SystemUI. */ synchronized void onDisplayInfoChanged(DisplayInfo displayInfo) { - setDisplayInfo(displayInfo); + mDisplayInfo.copyFrom(displayInfo); notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */); } @@ -315,7 +335,7 @@ class PinnedStackController { } else if (targetBounds.isEmpty()) { // The stack is null, we are just initializing the stack, so just store the display // info and ignore - setDisplayInfo(displayInfo); + mDisplayInfo.copyFrom(displayInfo); outBounds.setEmpty(); return false; } @@ -325,8 +345,7 @@ class PinnedStackController { // Calculate the snap fraction of the current stack along the old movement bounds final float snapFraction = getSnapFraction(postChangeStackBounds); - - setDisplayInfo(displayInfo); + mDisplayInfo.copyFrom(displayInfo); // Calculate the stack bounds in the new orientation to the same same fraction along the // rotated movement bounds. @@ -387,11 +406,8 @@ class PinnedStackController { void setAspectRatio(float aspectRatio) { if (Float.compare(mAspectRatio, aspectRatio) != 0) { mAspectRatio = aspectRatio; - notifyAspectRatioChanged(aspectRatio); notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */); - notifyPrepareAnimation(null /* sourceHintRect */, aspectRatio, - null /* stackBounds */); } } @@ -413,10 +429,6 @@ class PinnedStackController { notifyActionsChanged(mActions); } - void prepareAnimation(Rect sourceRectHint, float aspectRatio, Rect stackBounds) { - notifyPrepareAnimation(sourceRectHint, aspectRatio, stackBounds); - } - private boolean isSameDimensionAndRotation(@NonNull DisplayInfo display1, @NonNull DisplayInfo display2) { Preconditions.checkNotNull(display1); @@ -449,15 +461,6 @@ class PinnedStackController { } } - private void notifyAspectRatioChanged(float aspectRatio) { - if (mPinnedStackListener == null) return; - try { - mPinnedStackListener.onAspectRatioChanged(aspectRatio); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering aspect ratio changed event.", e); - } - } - /** * Notifies listeners that the PIP minimized state has changed. */ @@ -494,13 +497,23 @@ class PinnedStackController { return; } try { - final Rect animatingBounds = new Rect(); + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + final Rect normalBounds = getDefaultBounds(INVALID_SNAP_FRACTION); + if (isValidPictureInPictureAspectRatio(mAspectRatio)) { + transformBoundsToAspectRatio(normalBounds, mAspectRatio, + false /* useCurrentMinEdgeSize */); + } + final Rect animatingBounds = mTmpAnimatingBoundsRect; final TaskStack pinnedStack = mDisplayContent.getPinnedStack(); if (pinnedStack != null) { pinnedStack.getAnimationOrCurrentBounds(animatingBounds); + } else { + animatingBounds.set(normalBounds); } - mPinnedStackListener.onMovementBoundsChanged(animatingBounds, - fromImeAdjustment, fromShelfAdjustment); + mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, + animatingBounds, fromImeAdjustment, fromShelfAdjustment, + mDisplayInfo.rotation); } catch (RemoteException e) { Slog.e(TAG_WM, "Error delivering actions changed event.", e); } @@ -508,30 +521,6 @@ class PinnedStackController { } /** - * Notifies listeners that the PIP animation is about to happen. - */ - private void notifyDisplayInfoChanged(DisplayInfo displayInfo) { - if (mPinnedStackListener == null) return; - try { - mPinnedStackListener.onDisplayInfoChanged(displayInfo); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering DisplayInfo changed event.", e); - } - } - - /** - * Notifies listeners that the PIP animation is about to happen. - */ - private void notifyPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect stackBounds) { - if (mPinnedStackListener == null) return; - try { - mPinnedStackListener.onPrepareAnimation(sourceRectHint, aspectRatio, stackBounds); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering prepare animation event.", e); - } - } - - /** * @return the bounds on the screen that the PIP can be visible in. */ private void getInsetBounds(Rect outRect) { @@ -615,6 +604,7 @@ class PinnedStackController { pw.println(prefix + " mImeHeight=" + mImeHeight); pw.println(prefix + " mIsShelfShowing=" + mIsShelfShowing); pw.println(prefix + " mShelfHeight=" + mShelfHeight); + pw.println(prefix + " mReentrySnapFraction=" + mReentrySnapFraction); pw.println(prefix + " mIsMinimized=" + mIsMinimized); pw.println(prefix + " mAspectRatio=" + mAspectRatio); pw.println(prefix + " mMinAspectRatio=" + mMinAspectRatio); diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index d9e30a2da9a5..510a18fbfc22 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -959,6 +959,10 @@ class RootActivityContainer extends ConfigurationContainer // Need to make sure the pinned stack exist so we can resize it below... stack = display.getOrCreateStack(WINDOWING_MODE_PINNED, r.getActivityType(), ON_TOP); + // Calculate the target bounds here before the task is reparented back into pinned windowing + // mode (which will reset the saved bounds) + final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio); + try { final TaskRecord task = r.getTaskRecord(); // Resize the pinned stack to match the current size of the task the activity we are @@ -997,14 +1001,9 @@ class RootActivityContainer extends ConfigurationContainer mService.continueWindowLayout(); } - // Notify the pinned stack controller to prepare the PiP animation, expect callback - // delivered from SystemUI to WM to start the animation. - final PinnedStackController pinnedStackController = - display.mDisplayContent.getPinnedStackController(); - pinnedStackController.prepareAnimation(sourceHintBounds, aspectRatio, - null /* stackBounds */); + stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */, + true /* fromFullscreen */); - // TODO: revisit the following statement after the animation is moved from WM to SysUI. // Update the visibility of all activities after the they have been reparented to the new // stack. This MUST run after the animation above is scheduled to ensure that the windows // drawn signal is scheduled after the bounds animation start call on the bounds animator diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 58542e582067..239bd004705f 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -1661,6 +1661,40 @@ public class TaskStack extends WindowContainer<Task> implements } /** + * @return the current stack bounds transformed to the given {@param aspectRatio}. If + * the default bounds is {@code null}, then the {@param aspectRatio} is applied to the + * default bounds. + */ + Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) { + if (!mWmService.mAtmService.mSupportsPictureInPicture) { + return null; + } + + final DisplayContent displayContent = getDisplayContent(); + if (displayContent == null) { + return null; + } + + if (!inPinnedWindowingMode()) { + return null; + } + + final PinnedStackController pinnedStackController = + displayContent.getPinnedStackController(); + if (stackBounds == null) { + // Calculate the aspect ratio bounds from the default bounds + stackBounds = pinnedStackController.getDefaultOrLastSavedBounds(); + } + + if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) { + return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio, + true /* useCurrentMinEdgeSize */); + } else { + return stackBounds; + } + } + + /** * Animates the pinned stack. */ void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds, @@ -1737,11 +1771,6 @@ public class TaskStack extends WindowContainer<Task> implements return; } - final DisplayContent displayContent = getDisplayContent(); - if (displayContent == null) { - return; - } - if (!inPinnedWindowingMode()) { return; } @@ -1752,10 +1781,13 @@ public class TaskStack extends WindowContainer<Task> implements if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) { return; } - - // Notify the pinned stack controller about aspect ratio change. - // This would result a callback delivered from SystemUI to WM to start animation, - // if the bounds are ought to be altered due to aspect ratio change. + getAnimationOrCurrentBounds(mTmpFromBounds); + mTmpToBounds.set(mTmpFromBounds); + getPictureInPictureBounds(aspectRatio, mTmpToBounds); + if (!mTmpToBounds.equals(mTmpFromBounds)) { + animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */, + -1 /* duration */, false /* fromFullscreen */); + } pinnedStackController.setAspectRatio( pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio) ? aspectRatio : -1f); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index 1731f7cdd59c..e6d76329ee83 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -38,6 +38,7 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; +import android.graphics.Rect; import android.os.UserHandle; import android.service.voice.IVoiceInteractionSession; import android.testing.DexmakerShareClassLoaderRule; @@ -432,7 +433,12 @@ class ActivityTestsBase { final ActivityStackSupervisor supervisor = mRootActivityContainer.mStackSupervisor; if (mWindowingMode == WINDOWING_MODE_PINNED) { stack = new ActivityStack(mDisplay, stackId, supervisor, - mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop); + mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop) { + @Override + Rect getDefaultPictureInPictureBounds(float aspectRatio) { + return new Rect(50, 50, 100, 100); + } + }; } else { stack = new ActivityStack(mDisplay, stackId, supervisor, mWindowingMode, mActivityType, mOnTop); diff --git a/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java index e9c226340164..efd468f1f77a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java @@ -66,8 +66,8 @@ public class PinnedStackControllerTest extends WindowTestsBase { verify(mIPinnedStackListener).onImeVisibilityChanged(false, 0); verify(mIPinnedStackListener).onShelfVisibilityChanged(false, 0); - verify(mIPinnedStackListener).onMovementBoundsChanged(any(), eq(false), - eq(false)); + verify(mIPinnedStackListener).onMovementBoundsChanged(any(), any(), any(), eq(false), + eq(false), anyInt()); verify(mIPinnedStackListener).onActionsChanged(any()); verify(mIPinnedStackListener).onMinimizedStateChanged(anyBoolean()); @@ -75,8 +75,8 @@ public class PinnedStackControllerTest extends WindowTestsBase { mWm.setShelfHeight(true, SHELF_HEIGHT); verify(mIPinnedStackListener).onShelfVisibilityChanged(true, SHELF_HEIGHT); - verify(mIPinnedStackListener).onMovementBoundsChanged(any(), eq(false), - eq(true)); + verify(mIPinnedStackListener).onMovementBoundsChanged(any(), any(), any(), eq(false), + eq(true), anyInt()); verify(mIPinnedStackListener, never()).onImeVisibilityChanged(anyBoolean(), anyInt()); } } |