From 579eb8936257bca0a231c7f82bb8f6d408f76492 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Tue, 17 May 2022 17:37:55 -0700 Subject: [PATCH] Detect Remove-pip transaction to properly close multi-activity pips Multi-activity pip converts setWindowingMode(UNDEFINED) into a "reparent pip activity + move-to-front" when expanding pip. Shell doesn't know whether a pip is multi-activity or not, so it just makes a WCT with setWindowingMode(UNDEFINED) AND reorder-to-back. The problem is that setWindowingMode happens first which triggers the "merge + move-to-front" logic -- the reorder command was for the unmerged task so it just gets ignored. This CL basically checks if the WCT also has a move-to-back in addition to setMode(UNDEFINED) and, if so, uses the "workaround" found in removePinnedRootTaskInSurfaceTransaction to prevent setWindowingMode(UNDEFINED) from doing the wrong thing: it sets FORCE_HIDDEN_FOR_PINNED_TASK. Bug: 232954259 Test: open multi-activity pip (eg. ApiDemos). Go to pip. close it via the X button. Change-Id: Iaafbc1c930eb1bcfb427533ae28ef9a823d6b9c6 --- .../server/wm/WindowOrganizerController.java | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 59a393ad40d6a..128b3292983e6 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.ActivityManager.isStartResultSuccessful; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.DEFAULT_DISPLAY; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT; @@ -42,6 +43,7 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.server.wm.ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED; import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; +import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK; import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; @@ -395,6 +397,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub effects |= TRANSACT_EFFECTS_LIFECYCLE; } } + final List hops = t.getHierarchyOps(); + final int hopSize = hops.size(); ArraySet haveConfigChanges = new ArraySet<>(); Iterator> entries = t.getChanges().entrySet().iterator(); @@ -422,10 +426,33 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub transition.setCanPipOnFinish(false /* canPipOnFinish */); } } + // A bit hacky, but we need to detect "remove PiP" so that we can "wrap" the + // setWindowingMode call in force-hidden. + boolean forceHiddenForPip = false; + if (wc.asTask() != null && wc.inPinnedWindowingMode() + && entry.getValue().getWindowingMode() == WINDOWING_MODE_UNDEFINED) { + // We are in pip and going to undefined. Now search hierarchy ops to determine + // whether we are removing pip or expanding pip. + for (int i = 0; i < hopSize; ++i) { + final WindowContainerTransaction.HierarchyOp hop = hops.get(i); + if (hop.getType() != HIERARCHY_OP_TYPE_REORDER) continue; + final WindowContainer hopWc = WindowContainer.fromBinder( + hop.getContainer()); + if (!wc.equals(hopWc)) continue; + forceHiddenForPip = !hop.getToTop(); + } + } + if (forceHiddenForPip) { + wc.asTask().setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */); + } int containerEffect = applyWindowContainerChange(wc, entry.getValue()); effects |= containerEffect; + if (forceHiddenForPip) { + wc.asTask().setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, false /* set */); + } + // Lifecycle changes will trigger ensureConfig for everything. if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0 && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) { @@ -433,8 +460,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } // Hierarchy changes - final List hops = t.getHierarchyOps(); - final int hopSize = hops.size(); if (hopSize > 0) { final boolean isInLockTaskMode = mService.isInLockTaskMode(); for (int i = 0; i < hopSize; ++i) {