Loading services/core/java/com/android/server/wm/ActivityStackSupervisor.java +15 −6 Original line number Original line Diff line number Diff line Loading @@ -1504,13 +1504,22 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) { void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) { task.removeTaskActivitiesLocked(reason); if (task.mInRemoveTask) { // Prevent recursion. return; } task.mInRemoveTask = true; try { task.performClearTask(reason); cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); mService.getLockTaskController().clearLockedTask(task); mService.getLockTaskController().clearLockedTask(task); mService.getTaskChangeNotificationController().notifyTaskStackChanged(); mService.getTaskChangeNotificationController().notifyTaskStackChanged(); if (task.isPersistable) { if (task.isPersistable) { mService.notifyTaskPersisterLocked(null, true); mService.notifyTaskPersisterLocked(null, true); } } } finally { task.mInRemoveTask = false; } } } void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { Loading services/core/java/com/android/server/wm/Task.java +10 −11 Original line number Original line Diff line number Diff line Loading @@ -435,6 +435,13 @@ class Task extends WindowContainer<WindowContainer> { static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; private int mForceHiddenFlags = 0; private int mForceHiddenFlags = 0; // TODO(b/160201781): Revisit double invocation issue in Task#removeChild. /** * Skip {@link ActivityStackSupervisor#removeTask(Task, boolean, boolean, String)} execution if * {@code true} to prevent double traversal of {@link #mChildren} in a loop. */ boolean mInRemoveTask; // When non-null, this is a transaction that will get applied on the next frame returned after // When non-null, this is a transaction that will get applied on the next frame returned after // a relayout is requested from the client. While this is only valid on a leaf task; since the // a relayout is requested from the client. While this is only valid on a leaf task; since the // transaction can effect an ancestor task, this also needs to keep track of the ancestor task // transaction can effect an ancestor task, this also needs to keep track of the ancestor task Loading Loading @@ -1496,11 +1503,8 @@ class Task extends WindowContainer<WindowContainer> { return autoRemoveRecents || (!hasChild() && !getHasBeenVisible()); return autoRemoveRecents || (!hasChild() && !getHasBeenVisible()); } } /** /** Completely remove all activities associated with an existing task. */ * Completely remove all activities associated with an existing void performClearTask(String reason) { * task starting at a specified index. */ private void performClearTaskAtIndexLocked(String reason) { // Broken down into to cases to avoid object create due to capturing mStack. // Broken down into to cases to avoid object create due to capturing mStack. if (getStack() == null) { if (getStack() == null) { forAllActivities((r) -> { forAllActivities((r) -> { Loading @@ -1524,7 +1528,7 @@ class Task extends WindowContainer<WindowContainer> { */ */ void performClearTaskLocked() { void performClearTaskLocked() { mReuseTask = true; mReuseTask = true; performClearTaskAtIndexLocked("clear-task-all"); performClearTask("clear-task-all"); mReuseTask = false; mReuseTask = false; } } Loading Loading @@ -1585,11 +1589,6 @@ class Task extends WindowContainer<WindowContainer> { return false; return false; } } void removeTaskActivitiesLocked(String reason) { // Just remove the entire task. performClearTaskAtIndexLocked(reason); } String lockTaskAuthToString() { String lockTaskAuthToString() { switch (mLockTaskAuth) { switch (mLockTaskAuth) { case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK"; case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK"; Loading services/tests/wmtests/src/com/android/server/wm/TaskTests.java +28 −0 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations; import android.graphics.Point; import android.graphics.Point; Loading Loading @@ -158,4 +160,30 @@ public class TaskTests extends WindowTestsBase { assertEquals(activity1, task1.isInTask(activity1)); assertEquals(activity1, task1.isInTask(activity1)); assertNull(task1.isInTask(activity2)); assertNull(task1.isInTask(activity2)); } } @Test public void testRemoveChildForOverlayTask() { final Task task = createTaskStackOnDisplay(mDisplayContent); final int taskId = task.mTaskId; final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(mDisplayContent, task); final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(mDisplayContent, task); final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(mDisplayContent, task); activity1.setTaskOverlay(true); activity2.setTaskOverlay(true); activity3.setTaskOverlay(true); assertEquals(3, task.getChildCount()); assertTrue(task.onlyHasTaskOverlayActivities(true)); task.removeChild(activity1); verify(task.mStackSupervisor).removeTask(any(), anyBoolean(), anyBoolean(), anyString()); assertEquals(2, task.getChildCount()); task.forAllActivities((r) -> { assertTrue(r.finishing); }); } } } Loading
services/core/java/com/android/server/wm/ActivityStackSupervisor.java +15 −6 Original line number Original line Diff line number Diff line Loading @@ -1504,13 +1504,22 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } } void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) { void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) { task.removeTaskActivitiesLocked(reason); if (task.mInRemoveTask) { // Prevent recursion. return; } task.mInRemoveTask = true; try { task.performClearTask(reason); cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); mService.getLockTaskController().clearLockedTask(task); mService.getLockTaskController().clearLockedTask(task); mService.getTaskChangeNotificationController().notifyTaskStackChanged(); mService.getTaskChangeNotificationController().notifyTaskStackChanged(); if (task.isPersistable) { if (task.isPersistable) { mService.notifyTaskPersisterLocked(null, true); mService.notifyTaskPersisterLocked(null, true); } } } finally { task.mInRemoveTask = false; } } } void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { Loading
services/core/java/com/android/server/wm/Task.java +10 −11 Original line number Original line Diff line number Diff line Loading @@ -435,6 +435,13 @@ class Task extends WindowContainer<WindowContainer> { static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; private int mForceHiddenFlags = 0; private int mForceHiddenFlags = 0; // TODO(b/160201781): Revisit double invocation issue in Task#removeChild. /** * Skip {@link ActivityStackSupervisor#removeTask(Task, boolean, boolean, String)} execution if * {@code true} to prevent double traversal of {@link #mChildren} in a loop. */ boolean mInRemoveTask; // When non-null, this is a transaction that will get applied on the next frame returned after // When non-null, this is a transaction that will get applied on the next frame returned after // a relayout is requested from the client. While this is only valid on a leaf task; since the // a relayout is requested from the client. While this is only valid on a leaf task; since the // transaction can effect an ancestor task, this also needs to keep track of the ancestor task // transaction can effect an ancestor task, this also needs to keep track of the ancestor task Loading Loading @@ -1496,11 +1503,8 @@ class Task extends WindowContainer<WindowContainer> { return autoRemoveRecents || (!hasChild() && !getHasBeenVisible()); return autoRemoveRecents || (!hasChild() && !getHasBeenVisible()); } } /** /** Completely remove all activities associated with an existing task. */ * Completely remove all activities associated with an existing void performClearTask(String reason) { * task starting at a specified index. */ private void performClearTaskAtIndexLocked(String reason) { // Broken down into to cases to avoid object create due to capturing mStack. // Broken down into to cases to avoid object create due to capturing mStack. if (getStack() == null) { if (getStack() == null) { forAllActivities((r) -> { forAllActivities((r) -> { Loading @@ -1524,7 +1528,7 @@ class Task extends WindowContainer<WindowContainer> { */ */ void performClearTaskLocked() { void performClearTaskLocked() { mReuseTask = true; mReuseTask = true; performClearTaskAtIndexLocked("clear-task-all"); performClearTask("clear-task-all"); mReuseTask = false; mReuseTask = false; } } Loading Loading @@ -1585,11 +1589,6 @@ class Task extends WindowContainer<WindowContainer> { return false; return false; } } void removeTaskActivitiesLocked(String reason) { // Just remove the entire task. performClearTaskAtIndexLocked(reason); } String lockTaskAuthToString() { String lockTaskAuthToString() { switch (mLockTaskAuth) { switch (mLockTaskAuth) { case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK"; case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK"; Loading
services/tests/wmtests/src/com/android/server/wm/TaskTests.java +28 −0 Original line number Original line Diff line number Diff line Loading @@ -28,6 +28,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.clearInvocations; import android.graphics.Point; import android.graphics.Point; Loading Loading @@ -158,4 +160,30 @@ public class TaskTests extends WindowTestsBase { assertEquals(activity1, task1.isInTask(activity1)); assertEquals(activity1, task1.isInTask(activity1)); assertNull(task1.isInTask(activity2)); assertNull(task1.isInTask(activity2)); } } @Test public void testRemoveChildForOverlayTask() { final Task task = createTaskStackOnDisplay(mDisplayContent); final int taskId = task.mTaskId; final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(mDisplayContent, task); final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(mDisplayContent, task); final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(mDisplayContent, task); activity1.setTaskOverlay(true); activity2.setTaskOverlay(true); activity3.setTaskOverlay(true); assertEquals(3, task.getChildCount()); assertTrue(task.onlyHasTaskOverlayActivities(true)); task.removeChild(activity1); verify(task.mStackSupervisor).removeTask(any(), anyBoolean(), anyBoolean(), anyString()); assertEquals(2, task.getChildCount()); task.forAllActivities((r) -> { assertTrue(r.finishing); }); } } }