diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 8b8ebe80f01f9..e476993f003f8 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -298,13 +298,6 @@ interface IActivityTaskManager { void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration, 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 moveTasksToFullscreenStack(int fromStackId, boolean onTop); boolean moveTopActivityToPinnedStack(int stackId, in Rect bounds); diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 6ce5e7cf506cc..af8b18482ea83 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -16,6 +16,9 @@ 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_BOUNDS; 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.Nullable; import android.app.ActivityManager; -import android.app.ActivityTaskManager; -import android.window.ITaskOrganizerController; import android.app.PictureInPictureParams; import android.content.Context; import android.content.pm.ActivityInfo; @@ -38,9 +39,9 @@ import android.os.Looper; import android.os.RemoteException; import android.util.Log; import android.util.Size; +import android.view.SurfaceControl; import android.window.ITaskOrganizer; import android.window.IWindowContainer; -import android.view.SurfaceControl; import android.window.WindowContainerTransaction; import android.window.WindowOrganizer; @@ -216,6 +217,29 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { 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 public void onTaskAppeared(ActivityManager.RunningTaskInfo info) { Objects.requireNonNull(info, "Requires RunningTaskInfo"); @@ -235,7 +259,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { mBoundsToRestore.put(mToken.asBinder(), currentBounds); if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) { scheduleAnimateResizePip(currentBounds, destinationBounds, - TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null); + TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, + null /* updateBoundsCallback */); } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { mUpdateHandler.post(() -> mPipAnimationController .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 public void onTaskVanished(ActivityManager.RunningTaskInfo info) { IWindowContainer token = info.token; @@ -259,7 +290,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } final Rect boundsToRestore = mBoundsToRestore.remove(token.asBinder()); scheduleAnimateResizePip(mLastReportedBounds, boundsToRestore, - TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, null); + TRANSITION_DIRECTION_TO_FULLSCREEN, mEnterExitAnimationDuration, + null /* updateBoundsCallback */); mInPip = false; } @@ -274,7 +306,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { getAspectRatioOrDefault(newParams), null /* bounds */, getMinimalSize(info.topActivityInfo)); 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); 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 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) { wct.scheduleFinishEnterPip(mToken, taskBounds); } else { diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index 449a2bca6abbb..7974281b956f7 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -219,11 +219,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback, cancelAnimations(); mMenuController.hideMenuWithoutResize(); mPipTaskOrganizer.getUpdateHandler().post(() -> { - try { - mActivityTaskManager.dismissPip(!skipAnimation, EXPAND_STACK_TO_FULLSCREEN_DURATION); - } catch (RemoteException e) { - Log.e(TAG, "Error expanding PiP activity", e); - } + mPipTaskOrganizer.dismissPip(skipAnimation ? 0 : EXPAND_STACK_TO_FULLSCREEN_DURATION); }); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index bf92542cdd63c..ce885ab543bcf 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -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 public void suppressResizeConfigChanges(boolean suppress) throws RemoteException { mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()"); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index da3ee39901377..8846fb8e09628 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -1113,7 +1113,6 @@ public class RecentTasksTest extends ActivityTestsBase { () -> mService.moveTaskToStack(0, INVALID_STACK_ID, true)); assertSecurityException(expectCallable, () -> mService.setTaskWindowingModeSplitScreenPrimary(0, true)); - assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0)); assertSecurityException(expectCallable, () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect())); assertSecurityException(expectCallable, () -> mService.getAllStackInfos());