Merge "Start PiP dismiss from SysUI via TaskOrganizer" into rvc-dev
This commit is contained in:
@@ -298,13 +298,6 @@ interface IActivityTaskManager {
|
|||||||
void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
|
void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
|
||||||
in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
|
in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
|
||||||
|
|
||||||
/**
|
|
||||||
* Dismisses PiP
|
|
||||||
* @param animate True if the dismissal should be animated.
|
|
||||||
* @param animationDuration The duration of the resize animation in milliseconds or -1 if the
|
|
||||||
* default animation duration should be used.
|
|
||||||
*/
|
|
||||||
void dismissPip(boolean animate, int animationDuration);
|
|
||||||
void suppressResizeConfigChanges(boolean suppress);
|
void suppressResizeConfigChanges(boolean suppress);
|
||||||
void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
|
void moveTasksToFullscreenStack(int fromStackId, boolean onTop);
|
||||||
boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
|
boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds);
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.systemui.pip;
|
package com.android.systemui.pip;
|
||||||
|
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
|
|
||||||
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
|
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
|
||||||
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
|
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
|
||||||
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
|
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
|
||||||
@@ -26,8 +29,6 @@ import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTI
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityTaskManager;
|
|
||||||
import android.window.ITaskOrganizerController;
|
|
||||||
import android.app.PictureInPictureParams;
|
import android.app.PictureInPictureParams;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
@@ -38,9 +39,9 @@ import android.os.Looper;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Size;
|
import android.util.Size;
|
||||||
|
import android.view.SurfaceControl;
|
||||||
import android.window.ITaskOrganizer;
|
import android.window.ITaskOrganizer;
|
||||||
import android.window.IWindowContainer;
|
import android.window.IWindowContainer;
|
||||||
import android.view.SurfaceControl;
|
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
import android.window.WindowOrganizer;
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
@@ -216,6 +217,29 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
mOneShotAnimationType = animationType;
|
mOneShotAnimationType = animationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismiss PiP, this is done in two phases using {@link WindowContainerTransaction}
|
||||||
|
* - setActivityWindowingMode to fullscreen at beginning of the transaction. without changing
|
||||||
|
* the windowing mode of the Task itself. This makes sure the activity render it's fullscreen
|
||||||
|
* configuration while the Task is still in PiP.
|
||||||
|
* - setWindowingMode to fullscreen at the end of transition
|
||||||
|
* @param animationDurationMs duration in millisecond for the exiting PiP transition
|
||||||
|
*/
|
||||||
|
public void dismissPip(int animationDurationMs) {
|
||||||
|
try {
|
||||||
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
|
||||||
|
WindowOrganizer.applyTransaction(wct);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Failed to apply container transaction", e);
|
||||||
|
}
|
||||||
|
final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
|
||||||
|
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
|
||||||
|
TRANSITION_DIRECTION_TO_FULLSCREEN, animationDurationMs,
|
||||||
|
null /* updateBoundsCallback */);
|
||||||
|
mInPip = false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskAppeared(ActivityManager.RunningTaskInfo info) {
|
public void onTaskAppeared(ActivityManager.RunningTaskInfo info) {
|
||||||
Objects.requireNonNull(info, "Requires RunningTaskInfo");
|
Objects.requireNonNull(info, "Requires RunningTaskInfo");
|
||||||
@@ -235,7 +259,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
mBoundsToRestore.put(mToken.asBinder(), currentBounds);
|
mBoundsToRestore.put(mToken.asBinder(), currentBounds);
|
||||||
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
|
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
|
||||||
scheduleAnimateResizePip(currentBounds, destinationBounds,
|
scheduleAnimateResizePip(currentBounds, destinationBounds,
|
||||||
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null);
|
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
|
||||||
|
null /* updateBoundsCallback */);
|
||||||
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
||||||
mUpdateHandler.post(() -> mPipAnimationController
|
mUpdateHandler.post(() -> mPipAnimationController
|
||||||
.getAnimator(mLeash, destinationBounds, 0f, 1f)
|
.getAnimator(mLeash, destinationBounds, 0f, 1f)
|
||||||
@@ -249,6 +274,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that dismissing PiP is now originated from SystemUI, see {@link #dismissPip(int)}.
|
||||||
|
* Meanwhile this callback is invoked whenever the task is removed. For instance:
|
||||||
|
* - as a result of removeStacksInWindowingModes from WM
|
||||||
|
* - activity itself is died
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
|
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
|
||||||
IWindowContainer token = info.token;
|
IWindowContainer token = info.token;
|
||||||
@@ -259,7 +290,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
}
|
}
|
||||||
final Rect boundsToRestore = mBoundsToRestore.remove(token.asBinder());
|
final Rect boundsToRestore = mBoundsToRestore.remove(token.asBinder());
|
||||||
scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore,
|
scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore,
|
||||||
TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null);
|
TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration,
|
||||||
|
null /* updateBoundsCallback */);
|
||||||
mInPip = false;
|
mInPip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +306,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
getAspectRatioOrDefault(newParams),
|
getAspectRatioOrDefault(newParams),
|
||||||
null /* bounds */, getMinimalSize(info.topActivityInfo));
|
null /* bounds */, getMinimalSize(info.topActivityInfo));
|
||||||
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
|
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
|
||||||
scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration, null);
|
scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
|
||||||
|
null /* updateBoundsCallback */);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -434,12 +467,19 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
}
|
}
|
||||||
mLastReportedBounds.set(destinationBounds);
|
mLastReportedBounds.set(destinationBounds);
|
||||||
try {
|
try {
|
||||||
// If we are animating to fullscreen, then we need to reset the override bounds on the
|
|
||||||
// task to ensure that the task "matches" the parent's bounds
|
|
||||||
Rect taskBounds = direction == TRANSITION_DIRECTION_TO_FULLSCREEN
|
|
||||||
? null
|
|
||||||
: destinationBounds;
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
|
final Rect taskBounds;
|
||||||
|
if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
|
||||||
|
// If we are animating to fullscreen, then we need to reset the override bounds
|
||||||
|
// on the task to ensure that the task "matches" the parent's bounds, this applies
|
||||||
|
// also to the final windowing mode, which should be reset to undefined rather than
|
||||||
|
// fullscreen.
|
||||||
|
taskBounds = null;
|
||||||
|
wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
|
||||||
|
.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
|
||||||
|
} else {
|
||||||
|
taskBounds = destinationBounds;
|
||||||
|
}
|
||||||
if (direction == TRANSITION_DIRECTION_TO_PIP) {
|
if (direction == TRANSITION_DIRECTION_TO_PIP) {
|
||||||
wct.scheduleFinishEnterPip(mToken, taskBounds);
|
wct.scheduleFinishEnterPip(mToken, taskBounds);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -219,11 +219,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
|
|||||||
cancelAnimations();
|
cancelAnimations();
|
||||||
mMenuController.hideMenuWithoutResize();
|
mMenuController.hideMenuWithoutResize();
|
||||||
mPipTaskOrganizer.getUpdateHandler().post(() -> {
|
mPipTaskOrganizer.getUpdateHandler().post(() -> {
|
||||||
try {
|
mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION);
|
||||||
mActivityTaskManager.dismissPip(!skipAnimation, EXPAND_STACK_TO_FULLSCREEN_DURATION);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(TAG, "Error expanding PiP activity", e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3986,35 +3986,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Dismisses Pip
|
|
||||||
* @param animate True if the dismissal should be animated.
|
|
||||||
* @param animationDuration The duration of the resize animation in milliseconds or -1 if the
|
|
||||||
* default animation duration should be used.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void dismissPip(boolean animate, int animationDuration) {
|
|
||||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
|
|
||||||
final long ident = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
synchronized (mGlobalLock) {
|
|
||||||
final ActivityStack stack =
|
|
||||||
mRootWindowContainer.getDefaultDisplay().getRootPinnedTask();
|
|
||||||
if (stack == null) {
|
|
||||||
Slog.w(TAG, "dismissPip: pinned stack not found.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
|
|
||||||
throw new IllegalArgumentException("Stack: " + stack
|
|
||||||
+ " doesn't support animated resize.");
|
|
||||||
}
|
|
||||||
stack.dismissPip();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(ident);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
|
public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
|
||||||
mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
|
mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
|
||||||
|
|||||||
@@ -1113,7 +1113,6 @@ public class RecentTasksTest extends ActivityTestsBase {
|
|||||||
() -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
|
() -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
|
||||||
assertSecurityException(expectCallable,
|
assertSecurityException(expectCallable,
|
||||||
() -> mService.setTaskWindowingModeSplitScreenPrimary(0, true));
|
() -> mService.setTaskWindowingModeSplitScreenPrimary(0, true));
|
||||||
assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
|
|
||||||
assertSecurityException(expectCallable,
|
assertSecurityException(expectCallable,
|
||||||
() -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
|
() -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
|
||||||
assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
|
assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
|
||||||
|
|||||||
Reference in New Issue
Block a user