From d285e6219aa2b2248e26a7c6df6225da64965e22 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Thu, 16 Mar 2023 09:34:12 +0000 Subject: [PATCH] Fix pip expand issue if parent task under split root If task have more than one activity and enter pip mode, WMS will create new task for that activity and reparent it back when it exit pip mode. This cause some issues if the origin task under split root such as UI abnormal or it cannot expand to fullscreen.(We expect it expand to fullscreen always when click expand button on pip.) Fix this by record the origin task id in taskInfo and use this id to check exit split first or not if such task still under split root when exit pip. Fix: 264002510 Test: manual Test: pass existing tests Change-Id: I673f8c7a677f16897700d2be3853d4b4a36df7dd --- core/java/android/app/TaskInfo.java | 11 +++++++++++ .../com/android/wm/shell/pip/PipTaskOrganizer.java | 10 ++++++++++ .../com/android/wm/shell/pip/phone/PipMenuView.java | 3 ++- .../wm/shell/splitscreen/SplitScreenController.java | 9 +++++++-- services/core/java/com/android/server/wm/Task.java | 2 ++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 8ee23aa8e67b9..aba4b2c0d591a 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -187,6 +187,14 @@ public class TaskInfo { */ public int launchIntoPipHostTaskId; + /** + * The task id of the parent Task of the launch-into-pip Activity, i.e., if task have more than + * one activity it will create new task for this activity, this id is the origin task id and + * the pip activity will be reparent to origin task when it exit pip mode. + * @hide + */ + public int lastParentTaskIdBeforePip; + /** * The {@link Rect} copied from {@link DisplayCutout#getSafeInsets()} if the cutout is not of * (LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS), @@ -503,6 +511,7 @@ public class TaskInfo { pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR); shouldDockBigOverlays = source.readBoolean(); launchIntoPipHostTaskId = source.readInt(); + lastParentTaskIdBeforePip = source.readInt(); displayCutoutInsets = source.readTypedObject(Rect.CREATOR); topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR); isResizeable = source.readBoolean(); @@ -549,6 +558,7 @@ public class TaskInfo { dest.writeTypedObject(pictureInPictureParams, flags); dest.writeBoolean(shouldDockBigOverlays); dest.writeInt(launchIntoPipHostTaskId); + dest.writeInt(lastParentTaskIdBeforePip); dest.writeTypedObject(displayCutoutInsets, flags); dest.writeTypedObject(topActivityInfo, flags); dest.writeBoolean(isResizeable); @@ -589,6 +599,7 @@ public class TaskInfo { + " pictureInPictureParams=" + pictureInPictureParams + " shouldDockBigOverlays=" + shouldDockBigOverlays + " launchIntoPipHostTaskId=" + launchIntoPipHostTaskId + + " lastParentTaskIdBeforePip=" + lastParentTaskIdBeforePip + " displayCutoutSafeInsets=" + displayCutoutInsets + " topActivityInfo=" + topActivityInfo + " launchCookies=" + launchCookies diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index eb336d56b62ce..7d43d7ce8e354 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -16,6 +16,7 @@ package com.android.wm.shell.pip; +import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; @@ -538,6 +539,15 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct, destinationBounds); return; } + if (mSplitScreenOptional.isPresent()) { + // If pip activity will reparent to origin task case and if the origin task still under + // split root, just exit split screen here to ensure it could expand to fullscreen. + SplitScreenController split = mSplitScreenOptional.get(); + if (split.isTaskInSplitScreen(mTaskInfo.lastParentTaskIdBeforePip)) { + split.exitSplitScreen(INVALID_TASK_ID, + SplitScreenController.EXIT_REASON_APP_FINISHED); + } + } mSyncTransactionQueue.queue(wct); mSyncTransactionQueue.runInSync(t -> { // Make sure to grab the latest source hint rect as it could have been diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java index 979b7c7dc31f4..167c0321d3ad2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java @@ -282,7 +282,8 @@ public class PipMenuView extends FrameLayout { public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { final boolean isSplitScreen = mSplitScreenControllerOptional.isPresent() - && mSplitScreenControllerOptional.get().isTaskInSplitScreen(taskInfo.taskId); + && mSplitScreenControllerOptional.get().isTaskInSplitScreenForeground( + taskInfo.taskId); mFocusedTaskAllowSplitScreen = isSplitScreen || (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN && taskInfo.supportsMultiWindow diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 94b9e907fa763..d5dbfa2d4e50e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -329,9 +329,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return mTaskOrganizer.getRunningTaskInfo(taskId); } + /** Check task is under split or not by taskId. */ public boolean isTaskInSplitScreen(int taskId) { - return isSplitScreenVisible() - && mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED; + return mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED; + } + + /** Check split is foreground and task is under split or not by taskId. */ + public boolean isTaskInSplitScreenForeground(int taskId) { + return isTaskInSplitScreen(taskId) && isSplitScreenVisible(); } public @SplitPosition int getSplitPosition(int taskId) { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index ddfd5ae2f27d1..e79a4dba03c4f 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -3448,6 +3448,8 @@ class Task extends TaskFragment { && info.pictureInPictureParams.isLaunchIntoPip() && top.getLastParentBeforePip() != null) ? top.getLastParentBeforePip().mTaskId : INVALID_TASK_ID; + info.lastParentTaskIdBeforePip = top != null && top.getLastParentBeforePip() != null + ? top.getLastParentBeforePip().mTaskId : INVALID_TASK_ID; info.shouldDockBigOverlays = top != null && top.shouldDockBigOverlays; info.mTopActivityLocusId = top != null ? top.getLocusId() : null;