diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 7e2efc04ea8ea..8d6ce4718aefe 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -552,9 +552,6 @@ public class PipTaskOrganizer extends TaskOrganizer { ? null : destinationBounds; // As for the final windowing mode, simply reset it to undefined. wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED); - if (mSplitDivider != null && direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN) { - wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */); - } } else { taskBounds = destinationBounds; } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 02a7aca38abe7..e67b3d715c84f 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -813,12 +813,4 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, updateVisibility(true /* visible */); } } - - /** @return the container token for the secondary split root task. */ - public WindowContainerToken getSecondaryRoot() { - if (mSplits == null || mSplits.mSecondary == null) { - return null; - } - return mSplits.mSecondary.token; - } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 4b427a24a1cc6..850b6576bc894 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1287,6 +1287,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } if (stack != null && stack.topRunningActivity() == this) { + // carry over the PictureInPictureParams to the parent stack without calling + // TaskOrganizerController#dispatchTaskInfoChanged. + // this is to ensure the stack holding up-to-dated pinned stack information + // when activity is re-parented to enter pip mode, see also + // RootWindowContainer#moveActivityToPinnedStack + stack.mPictureInPictureParams.copyOnlySet(pictureInPictureArgs); // make ensure the TaskOrganizer still works after re-parenting if (firstWindowDrawn) { stack.setHasBeenVisible(true); @@ -7771,6 +7777,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void setPictureInPictureParams(PictureInPictureParams p) { pictureInPictureArgs.copyOnlySet(p); - getTask().getRootTask().onPictureInPictureParamsChanged(); + getTask().getRootTask().setPictureInPictureParams(p); } } diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 1d72555787594..9df3f855ad86a 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -702,10 +702,8 @@ class ActivityStack extends Task { // Need to make sure windowing mode is supported. If we in the process of creating the stack // no need to resolve the windowing mode again as it is already resolved to the right mode. if (!creating) { - if (!taskDisplayArea.isValidWindowingMode(windowingMode, null /* ActivityRecord */, - topTask, getActivityType())) { - windowingMode = WINDOWING_MODE_UNDEFINED; - } + windowingMode = taskDisplayArea.validateWindowingMode(windowingMode, + null /* ActivityRecord */, topTask, getActivityType()); } if (taskDisplayArea.getRootSplitScreenPrimaryTask() == this && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 33715207c6ce3..fb7ba62b5fd2e 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -1440,7 +1440,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { mService.deferWindowLayout(); try { stack.setWindowingMode(WINDOWING_MODE_UNDEFINED); - stack.setBounds(null); if (toDisplay.getDisplayId() != stack.getDisplayId()) { stack.reparent(toDisplay.getDefaultTaskDisplayArea(), false /* onTop */); } else { diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index c93b7354999bd..9a30f1c8e11dc 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2170,7 +2170,7 @@ class RootWindowContainer extends WindowContainer final boolean singleActivity = task.getChildCount() == 1; final ActivityStack stack; if (singleActivity) { - stack = (ActivityStack) task; + stack = r.getRootTask(); } else { // In the case of multiple activities, we will create a new task for it and then // move the PIP activity into the task. @@ -2183,11 +2183,6 @@ class RootWindowContainer extends WindowContainer // up-to-dated pinned stack information on this newly created stack. r.reparent(stack, MAX_VALUE, reason); } - if (stack.getParent() != taskDisplayArea) { - // stack is nested, but pinned tasks need to be direct children of their - // display area, so reparent. - stack.reparent(taskDisplayArea, true /* onTop */); - } stack.setWindowingMode(WINDOWING_MODE_PINNED); // Reset the state that indicates it can enter PiP while pausing after we've moved it diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 85a31610964e9..caa0ddbdc2aee 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -109,6 +109,7 @@ import android.app.ActivityManager.TaskSnapshot; import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.AppGlobals; +import android.app.PictureInPictureParams; import android.app.TaskInfo; import android.app.WindowConfiguration; import android.content.ComponentName; @@ -488,6 +489,12 @@ class Task extends WindowContainer { */ boolean mTaskAppearedSent; + /** + * Last Picture-in-Picture params applicable to the task. Updated when the app + * enters Picture-in-Picture or when setPictureInPictureParams is called. + */ + PictureInPictureParams mPictureInPictureParams = new PictureInPictureParams.Builder().build(); + /** * This task was created by the task organizer which has the following implementations. *
    @@ -3585,11 +3592,10 @@ class Task extends WindowContainer { info.resizeMode = top != null ? top.mResizeMode : mResizeMode; info.topActivityType = top.getActivityType(); - ActivityRecord rootActivity = top.getRootActivity(); - if (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) { + if (mPictureInPictureParams.empty()) { info.pictureInPictureParams = null; } else { - info.pictureInPictureParams = rootActivity.pictureInPictureArgs; + info.pictureInPictureParams = mPictureInPictureParams; } info.topActivityInfo = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.info @@ -4505,7 +4511,8 @@ class Task extends WindowContainer { updateShadowsRadius(hasFocus, getPendingTransaction()); } - void onPictureInPictureParamsChanged() { + void setPictureInPictureParams(PictureInPictureParams p) { + mPictureInPictureParams.copyOnlySet(p); if (isOrganized()) { mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */); } diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 37a4c1f6849b5..0a1ee2b79711c 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; @@ -1332,16 +1333,16 @@ final class TaskDisplayArea extends DisplayArea { } /** - * Check if the requested windowing-mode is appropriate for the specified task and/or activity + * Check that the requested windowing-mode is appropriate for the specified task and/or activity * on this display. * * @param windowingMode The windowing-mode to validate. * @param r The {@link ActivityRecord} to check against. * @param task The {@link Task} to check against. * @param activityType An activity type. - * @return {@code true} if windowingMode is valid, {@code false} otherwise. + * @return The provided windowingMode or the closest valid mode which is appropriate. */ - boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, + int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType) { // Make sure the windowing mode we are trying to use makes sense for what is supported. boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow; @@ -1361,35 +1362,24 @@ final class TaskDisplayArea extends DisplayArea { } } - return windowingMode != WINDOWING_MODE_UNDEFINED - && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen, - supportsFreeform, supportsPip, activityType); - } - - /** - * Check that the requested windowing-mode is appropriate for the specified task and/or activity - * on this display. - * - * @param windowingMode The windowing-mode to validate. - * @param r The {@link ActivityRecord} to check against. - * @param task The {@link Task} to check against. - * @param activityType An activity type. - * @return The provided windowingMode or the closest valid mode which is appropriate. - */ - int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, - int activityType) { final boolean inSplitScreenMode = isSplitScreenModeActivated(); - if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { + if (!inSplitScreenMode + && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) { // Switch to the display's windowing mode if we are not in split-screen mode and we are // trying to launch in split-screen secondary. windowingMode = WINDOWING_MODE_UNDEFINED; - } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_UNDEFINED) { + } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN + || windowingMode == WINDOWING_MODE_UNDEFINED) + && supportsSplitScreen) { windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; } - if (!isValidWindowingMode(windowingMode, r, task, activityType)) { - return WINDOWING_MODE_UNDEFINED; + + if (windowingMode != WINDOWING_MODE_UNDEFINED + && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen, + supportsFreeform, supportsPip, activityType)) { + return windowingMode; } - return windowingMode; + return WINDOWING_MODE_UNDEFINED; } boolean isTopStack(ActivityStack stack) { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index fdc5c7bf0ce14..2ea58a028a0ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -836,7 +836,7 @@ public class WindowOrganizerTests extends WindowTestsBase { spyOn(record); doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean()); - record.getTask().setHasBeenVisible(true); + record.getRootTask().setHasBeenVisible(true); return record; }