diff options
4 files changed, 44 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 68884247df97..863e506b9d35 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -393,6 +393,10 @@ class TaskFragment extends WindowContainer<WindowContainer> { mTaskFragmentOrganizerProcessName = processName; } + void onTaskFragmentOrganizerRemoved() { + mTaskFragmentOrganizer = null; + } + /** Whether this TaskFragment is organized by the given {@code organizer}. */ boolean hasTaskFragmentOrganizer(ITaskFragmentOrganizer organizer) { return organizer != null && mTaskFragmentOrganizer != null diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index d4551becbaaf..602579fb4f9f 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -136,6 +136,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr void dispose() { while (!mOrganizedTaskFragments.isEmpty()) { final TaskFragment taskFragment = mOrganizedTaskFragments.get(0); + // Cleanup before remove to prevent it from sending any additional event, such as + // #onTaskFragmentVanished, to the removed organizer. + taskFragment.onTaskFragmentOrganizerRemoved(); taskFragment.removeImmediately(); mOrganizedTaskFragments.remove(taskFragment); } @@ -512,10 +515,21 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr mPendingTaskFragmentEvents.add(pendingEvent); } + boolean isOrganizerRegistered(ITaskFragmentOrganizer organizer) { + return mTaskFragmentOrganizerState.containsKey(organizer.asBinder()); + } + private void removeOrganizer(ITaskFragmentOrganizer organizer) { final TaskFragmentOrganizerState state = validateAndGetState(organizer); // remove all of the children of the organized TaskFragment state.dispose(); + // Remove any pending event of this organizer. + for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) { + final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i); + if (event.mTaskFragmentOrg.asBinder().equals(organizer.asBinder())) { + mPendingTaskFragmentEvents.remove(i); + } + } mTaskFragmentOrganizerState.remove(organizer.asBinder()); } diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 0f5655c74f31..ca6d9c793c96 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -386,6 +386,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId, @Nullable Transition transition, @NonNull CallerInfo caller, @Nullable Transition finishTransition) { + if (t.getTaskFragmentOrganizer() != null && !mTaskFragmentOrganizerController + .isOrganizerRegistered(t.getTaskFragmentOrganizer())) { + Slog.e(TAG, "Caller organizer=" + t.getTaskFragmentOrganizer() + + " is no longer registered"); + return; + } int effects = 0; ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId); mService.deferWindowLayout(); 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 97f0918e8136..eba27553937e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -420,6 +420,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { @Test public void testApplyTransaction_enforceHierarchyChange_setAdjacentRoots() throws RemoteException { + mAtm.mTaskFragmentOrganizerController.registerOrganizer(mIOrganizer); final TaskFragment taskFragment2 = new TaskFragment(mAtm, new Binder(), true /* createdByOrganizer */); final WindowContainerToken token2 = taskFragment2.mRemoteToken.toWindowContainerToken(); @@ -595,6 +596,25 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { } @Test + public void testApplyTransaction_skipTransactionForUnregisterOrganizer() { + final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent); + final IBinder fragmentToken = new Binder(); + + // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment. + createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + // Nothing should happen as the organizer is not registered. + assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); + + mController.registerOrganizer(mIOrganizer); + mAtm.mWindowOrganizerController.applyTransaction(mTransaction); + + // Successfully created when the organizer is registered. + assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); + } + + @Test public void testTaskFragmentInPip_startActivityInTaskFragment() { setupTaskFragmentInPip(); final ActivityRecord activity = mTaskFragment.getTopMostActivity(); |