From a32a2ffce210ae2583ab99659f1211d9067b4b53 Mon Sep 17 00:00:00 2001 From: Chris Li Date: Wed, 14 Dec 2022 18:23:03 +0800 Subject: [PATCH] Fix delay on TYPE_TASK_FRAGMENT_VANISHED Before, we call sendTaskFragmentVanished after the removeImmediately, which may not have any following activity paused/resumed to trigger relayout to dispatch the pending event to the organizer. Now, we call mWindowPlacerLocked.requestTraversal() to ensure the vanished event will be dispatched. Without this change, the splitInfo callback can be stucked on waiting for empty TaskFragment vanished event. Bug: 262666213 Test: atest CtsWindowManagerDeviceTestCases:TaskFragmentOrganizerTest Test: atest WmTests:TaskFragmentOrganizerControllerTest Change-Id: Ibf76af205a5fc91400bdd5fc967a0d13591cfe92 --- .../com/android/server/wm/TaskFragment.java | 7 ++++- .../wm/TaskFragmentOrganizerController.java | 26 +++++++++++-------- .../TaskFragmentOrganizerControllerTest.java | 3 +++ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index ae4f8947cc863..d2ee9eeab6fe1 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -227,10 +227,15 @@ class TaskFragment extends WindowContainer { private TaskFragment mCompanionTaskFragment; /** - * Prevents duplicate calls to onTaskAppeared. + * Prevents duplicate calls to onTaskFragmentAppeared. */ boolean mTaskFragmentAppearedSent; + /** + * Prevents unnecessary callbacks after onTaskFragmentVanished. + */ + boolean mTaskFragmentVanishedSent; + /** * The last running activity of the TaskFragment was finished due to clear task while launching * an activity in the Task. diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index 6e4df794f8d86..90a0dffa25f2f 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -553,6 +553,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr void onTaskFragmentAppeared(@NonNull ITaskFragmentOrganizer organizer, @NonNull TaskFragment taskFragment) { + if (taskFragment.mTaskFragmentVanishedSent) { + return; + } if (taskFragment.getTask() == null) { Slog.w(TAG, "onTaskFragmentAppeared failed because it is not attached tf=" + taskFragment); @@ -574,6 +577,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr void onTaskFragmentInfoChanged(@NonNull ITaskFragmentOrganizer organizer, @NonNull TaskFragment taskFragment) { + if (taskFragment.mTaskFragmentVanishedSent) { + return; + } validateAndGetState(organizer); if (!taskFragment.mTaskFragmentAppearedSent) { // Skip if TaskFragment still not appeared. @@ -586,10 +592,6 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr .setTaskFragment(taskFragment) .build(); } else { - if (pendingEvent.mEventType == PendingTaskFragmentEvent.EVENT_VANISHED) { - // Skipped the info changed event if vanished event is pending. - return; - } // Remove and add for re-ordering. removePendingEvent(pendingEvent); // Reset the defer time when TaskFragment is changed, so that it can check again if @@ -602,6 +604,10 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr void onTaskFragmentVanished(@NonNull ITaskFragmentOrganizer organizer, @NonNull TaskFragment taskFragment) { + if (taskFragment.mTaskFragmentVanishedSent) { + return; + } + taskFragment.mTaskFragmentVanishedSent = true; final TaskFragmentOrganizerState state = validateAndGetState(organizer); final List pendingEvents = mPendingTaskFragmentEvents .get(organizer.asBinder()); @@ -617,20 +623,18 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr .setTaskFragment(taskFragment) .build()); state.removeTaskFragment(taskFragment); + // Make sure the vanished event will be dispatched if there are no other changes. + mAtmService.mWindowManager.mWindowPlacerLocked.requestTraversal(); } void onTaskFragmentError(@NonNull ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken, @Nullable TaskFragment taskFragment, int opType, @NonNull Throwable exception) { - validateAndGetState(organizer); - Slog.w(TAG, "onTaskFragmentError ", exception); - final PendingTaskFragmentEvent vanishedEvent = taskFragment != null - ? getPendingTaskFragmentEvent(taskFragment, PendingTaskFragmentEvent.EVENT_VANISHED) - : null; - if (vanishedEvent != null) { - // No need to notify if the TaskFragment has been removed. + if (taskFragment != null && taskFragment.mTaskFragmentVanishedSent) { return; } + validateAndGetState(organizer); + Slog.w(TAG, "onTaskFragmentError ", exception); addPendingEvent(new PendingTaskFragmentEvent.Builder( PendingTaskFragmentEvent.EVENT_ERROR, organizer) .setErrorCallbackToken(errorCallbackToken) diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index db65f49465bc8..140051d5c9b1f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -247,6 +247,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mController.dispatchPendingEvents(); + assertTrue(mTaskFragment.mTaskFragmentVanishedSent); assertTaskFragmentVanishedTransaction(); } @@ -259,10 +260,12 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { mController.onTaskFragmentVanished(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mController.dispatchPendingEvents(); + assertTrue(mTaskFragment.mTaskFragmentVanishedSent); assertTaskFragmentVanishedTransaction(); // Not trigger onTaskFragmentInfoChanged. // Call onTaskFragmentAppeared before calling onTaskFragmentInfoChanged. + mTaskFragment.mTaskFragmentVanishedSent = false; mController.onTaskFragmentAppeared(mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment); mController.dispatchPendingEvents(); clearInvocations(mOrganizer);