From b131a1ed37e270382df1e3907457c5e80c7cad54 Mon Sep 17 00:00:00 2001 From: Kazuki Takise Date: Thu, 20 Oct 2022 13:27:41 +0900 Subject: [PATCH] Shift focus when a task with multiple activities gets removed When ActivityTaskManager#removeTask is called for a task with multiple activities in a freeform environment, no activity in other tasks gets resumed, the corresponding transition doesn't run, and it times out. This doesn't happen in fullscreen environments becaue the tasks behind get visible when the top task is removed and one of them gets resumed on another code path. If a task has only one activity in a freeform environment, when the top activity is removed, there's no activity left, so adjustFocusToNextFocusableTask() is called in finishIfPossible() and the corresponding app transition will be eventually run. However, if there are multiple activities, when the top activity is removed, currently finishIfPossible() believes that there are some other activities left in the task although they will be removed just after this. This CL fixes this by reverse the order of removing activities in ActivityTaskManager#removeTask(). This way, at the point the top activity is removed, all the other activities have been gone and adjustFocusToNextFocusableTask() is called properly. Bug: 249658397 Test: WM CTS Change-Id: I769208a7c90a8e82e4bb4c4168f19bca3cf3507e --- services/core/java/com/android/server/wm/Task.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 66d7af9b4f6ca..5fd76d81d1744 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -1591,6 +1591,11 @@ class Task extends TaskFragment { removeChild(r, reason); }); } else { + // Finish or destroy apps from the bottom to ensure that all the other activity have + // been finished and the top task in another task gets resumed when a top activity is + // removed. Otherwise, shell transitions wouldn't run because there would be no event + // that sets the transition ready. + final boolean traverseTopToBottom = !mTransitionController.isShellTransitionsEnabled(); forAllActivities((r) -> { if (r.finishing || (excludingTaskOverlay && r.isTaskOverlay())) { return; @@ -1604,7 +1609,7 @@ class Task extends TaskFragment { } else { r.destroyIfPossible(reason); } - }); + }, traverseTopToBottom); } }