diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index bcad7586b9189..d88d76c1f96f0 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -783,6 +783,11 @@ class ActivityStack extends Task { if (currentMode == WINDOWING_MODE_PINNED) { mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned(); } + if (likelyResolvedMode == WINDOWING_MODE_PINNED + && taskDisplayArea.getRootPinnedTask() != null) { + // Can only have 1 pip at a time, so replace an existing pip + taskDisplayArea.getRootPinnedTask().dismissPip(); + } if (likelyResolvedMode != WINDOWING_MODE_FULLSCREEN && topActivity != null && !topActivity.noDisplay && topActivity.isNonResizableOrForcedResizable(likelyResolvedMode)) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 80a1a4592ff3d..8d46a6769bc82 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.ROTATION_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 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_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; @@ -5028,6 +5029,7 @@ class DisplayContent extends WindowContainer { mForceShowForAllUsers = forceShowForAllUsers; } + @Override public boolean isAttached() { final TaskDisplayArea taskDisplayArea = getDisplayArea(); return taskDisplayArea != null && !taskDisplayArea.isRemoved(); diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index ea9a3629a40f4..d71e56106e180 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -879,6 +879,11 @@ final class TaskDisplayArea extends DisplayArea { + windowingMode); } + if (windowingMode == WINDOWING_MODE_PINNED && getRootPinnedTask() != null) { + // Only 1 stack can be PINNED at a time, so dismiss the existing one + getRootPinnedTask().dismissPip(); + } + final int stackId = getNextStackId(); return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent, createdByOrganizer); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index fba22dd4e9dfb..7219164ad2f14 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -737,6 +737,10 @@ class WindowContainer extends ConfigurationContainer< return parent != null ? parent.getDisplayArea() : null; } + boolean isAttached() { + return getDisplayArea() != null; + } + void setWaitingForDrawnIfResizingChanged() { for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowContainer wc = mChildren.get(i); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 86bc013e36389..d9c0219c47794 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -129,6 +129,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub final Map.Entry entry = entries.next(); final WindowContainer wc = WindowContainer.fromBinder(entry.getKey()); + if (!wc.isAttached()) { + Slog.e(TAG, "Attempt to operate on detached container: " + wc); + continue; + } int containerEffect = applyWindowContainerChange(wc, entry.getValue()); effects |= containerEffect; @@ -146,6 +150,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub for (int i = 0, n = hops.size(); i < n; ++i) { final WindowContainerTransaction.HierarchyOp hop = hops.get(i); final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer()); + if (!wc.isAttached()) { + Slog.e(TAG, "Attempt to operate on detached container: " + wc); + continue; + } effects |= sanitizeAndApplyHierarchyOp(wc, hop); } if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index a7085334bece1..52a51875427f6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -172,7 +172,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase { assertGetOrCreateStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, type, candidateTask, false /* reuseCandidate */); assertGetOrCreateStack(WINDOWING_MODE_PINNED, type, candidateTask, - false /* reuseCandidate */); + true /* reuseCandidate */); final int windowingMode = WINDOWING_MODE_FULLSCREEN; assertGetOrCreateStack(windowingMode, ACTIVITY_TYPE_HOME, candidateTask,