diff --git a/api/test-current.txt b/api/test-current.txt index 777cbc540b540..ca291f373be20 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -505,6 +505,11 @@ package android.app { method public boolean isStatusBarExpansionDisabled(); } + public class TaskInfo { + method @NonNull public android.content.res.Configuration getConfiguration(); + method @NonNull public android.window.WindowContainerToken getToken(); + } + public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener { method public android.widget.TimePicker getTimePicker(); } diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index 0173731995dda..c7a2a1e11c9eb 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -20,6 +20,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Intent; @@ -196,6 +197,20 @@ public class TaskInfo { return resizeMode != RESIZE_MODE_UNRESIZEABLE; } + /** @hide */ + @NonNull + @TestApi + public WindowContainerToken getToken() { + return token; + } + + /** @hide */ + @NonNull + @TestApi + public Configuration getConfiguration() { + return configuration; + } + /** * Reads the TaskInfo from a parcel. */ diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index df5cfee6c01c4..66e1b1758d851 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4435,19 +4435,20 @@ class Task extends WindowContainer { // Let the old organizer know it has lost control. sendTaskVanished(); mTaskOrganizer = organizer; - sendTaskAppeared(); - onTaskOrganizerChanged(); - return true; - } - void taskOrganizerUnregistered() { - mTaskOrganizer = null; - mTaskAppearedSent = false; - mLastTaskOrganizerWindowingMode = -1; - onTaskOrganizerChanged(); - if (mCreatedByOrganizer) { - removeImmediately(); + if (mTaskOrganizer != null) { + sendTaskAppeared(); + } else { + // No longer managed by any organizer. + mTaskAppearedSent = false; + mLastTaskOrganizerWindowingMode = -1; + setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */); + if (mCreatedByOrganizer) { + removeImmediately(); + } } + + return true; } /** @@ -4484,14 +4485,6 @@ class Task extends WindowContainer { return result; } - private void onTaskOrganizerChanged() { - if (mTaskOrganizer == null) { - // If this task is no longer controlled by a task organizer, then reset the force hidden - // state - setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */); - } - } - @Override void setSurfaceControl(SurfaceControl sc) { super.setSurfaceControl(sc); diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index adc50bf704460..306c100e651c9 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -218,18 +218,24 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } void dispose() { - releaseTasks(); + // Move organizer from managing specific windowing modes for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) { mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.getBinder()); } - } - private void releaseTasks() { - for (int i = mOrganizedTasks.size() - 1; i >= 0; i--) { - final Task t = mOrganizedTasks.get(i); - removeTask(t); - t.taskOrganizerUnregistered(); + // Update tasks currently managed by this organizer to the next one available if + // possible. + while (!mOrganizedTasks.isEmpty()) { + final Task t = mOrganizedTasks.get(0); + t.updateTaskOrganizerState(true /* forceUpdate */); + if (mOrganizedTasks.contains(t)) { + removeTask(t); + } } + + // Remove organizer state after removing tasks so we get a chance to send + // onTaskVanished. + mTaskOrganizerStates.remove(asBinder()); } void unlinkDeath() { @@ -313,16 +319,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { new TaskOrganizerState(organizer, uid)); } - if (orgs.size() == 1) { - // Only in the case where this is the root task organizer for the given - // windowing mode, we add report all existing tasks in that mode to the new - // task organizer. - mService.mRootWindowContainer.forAllTasks((task) -> { - if (task.getWindowingMode() == windowingMode) { - task.updateTaskOrganizerState(true /* forceUpdate */); - } - }); - } + mService.mRootWindowContainer.forAllTasks((task) -> { + if (task.getWindowingMode() == windowingMode) { + task.updateTaskOrganizerState(true /* forceUpdate */); + } + }); } } finally { Binder.restoreCallingIdentity(origId); @@ -335,7 +336,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - final TaskOrganizerState state = mTaskOrganizerStates.remove(organizer.asBinder()); + final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); if (state == null) { return; } @@ -367,7 +368,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { void onTaskVanished(ITaskOrganizer organizer, Task task) { final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); - state.removeTask(task); + if (state != null) { + state.removeTask(task); + } } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index f65328dcbd428..7d2e88014f456 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -81,7 +81,7 @@ import java.util.List; * Test class for {@link ITaskOrganizer} and {@link android.window.ITaskOrganizerController}. * * Build/Install/Run: - * atest WmTests:TaskOrganizerTests + * atest WmTests:WindowOrganizerTests */ @SmallTest @Presubmit @@ -264,15 +264,22 @@ public class WindowOrganizerTests extends WindowTestsBase { // newly entering the windowing mode. final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW); stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); - verify(organizer2).onTaskAppeared(any()); + // One each for task and task2 + verify(organizer2, times(2)).onTaskAppeared(any()); + verify(organizer2, times(0)).onTaskVanished(any()); + // One for task + verify(organizer).onTaskVanished(any()); assertTrue(stack2.isOrganized()); // Now we unregister the second one, the first one should automatically be reregistered // so we verify that it's now seeing changes. mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2); + verify(organizer, times(3)).onTaskAppeared(any()); + verify(organizer2, times(2)).onTaskVanished(any()); stack3.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); - verify(organizer, times(2)).onTaskAppeared(any()); + verify(organizer, times(4)).onTaskAppeared(any()); + verify(organizer2, times(2)).onTaskVanished(any()); assertTrue(stack3.isOrganized()); } @@ -902,12 +909,13 @@ public class WindowOrganizerTests extends WindowTestsBase { task.setHasBeenVisible(true); verify(organizer, times(1)).onTaskAppeared(any()); - task.taskOrganizerUnregistered(); + task.setTaskOrganizer(null); + verify(organizer, times(1)).onTaskVanished(any()); task.setTaskOrganizer(organizer); verify(organizer, times(2)).onTaskAppeared(any()); task.removeImmediately(); - verify(organizer).onTaskVanished(any()); + verify(organizer, times(2)).onTaskVanished(any()); } @Test