Revert "Move bounds calculation and snap fraction to SysUI"
This reverts commit e3ff139062.
Reason for revert: PinnedStackTests#testEnterPictureInPictureDiscardSavedPositionOnFinish flaky
Change-Id: I067c94d536b1db94523ef3eec3d443e0dc4cb575
This commit is contained in:
@@ -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.
|
||||
@@ -31,18 +29,16 @@ interface IPinnedStackController {
|
||||
*/
|
||||
oneway void setIsMinimized(boolean isMinimized);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
oneway void setMinEdgeSize(int minEdgeSize);
|
||||
|
||||
/**
|
||||
* @return what WM considers to be the current device rotation.
|
||||
*/
|
||||
int getDisplayRotation();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
void startAnimation(in Rect destinationBounds, in Rect sourceRectHint, int animationDuration);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -236,35 +237,59 @@ class PinnedStackController {
|
||||
Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current bounds (or the default bounds if there are no current bounds) with the
|
||||
* specified aspect ratio.
|
||||
*/
|
||||
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 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);
|
||||
}
|
||||
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,43 +497,29 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1660,6 +1660,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.
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user