Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f787e532 authored by Louis Chang's avatar Louis Chang
Browse files

Ensure all stacks got examined for removal

The top activity of the topmost stack was resumed. The next
focusable activity/stack would be brought to top while
removing the topmost stack. Since the stack order changed,
we did not remove the newly topmost stack while continuing
to remove stack one-down.

Bug: 121105810
Test: atest ActivityDisplayTests
Test: atest ActivityManagerDisplayLockedKeyguardTests

Change-Id: I4f840b8aa87c2bc3563572d83e9cd424e7a3e023
parent 2568f884
Loading
Loading
Loading
Loading
+18 −2
Original line number Original line Diff line number Diff line
@@ -626,6 +626,10 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
            return;
            return;
        }
        }


        // Collect the stacks that are necessary to be removed instead of performing the removal
        // by looping mStacks, so that we don't miss any stacks after the stack size changed or
        // stacks reordered.
        final ArrayList<ActivityStack> stacks = new ArrayList<>();
        for (int j = windowingModes.length - 1 ; j >= 0; --j) {
        for (int j = windowingModes.length - 1 ; j >= 0; --j) {
            final int windowingMode = windowingModes[j];
            final int windowingMode = windowingModes[j];
            for (int i = mStacks.size() - 1; i >= 0; --i) {
            for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -636,9 +640,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
                if (stack.getWindowingMode() != windowingMode) {
                if (stack.getWindowingMode() != windowingMode) {
                    continue;
                    continue;
                }
                }
                mRootActivityContainer.mStackSupervisor.removeStack(stack);
                stacks.add(stack);
            }
            }
        }
        }

        for (int i = stacks.size() - 1; i >= 0; --i) {
            mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
        }
    }
    }


    void removeStacksWithActivityTypes(int... activityTypes) {
    void removeStacksWithActivityTypes(int... activityTypes) {
@@ -646,15 +654,23 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
            return;
            return;
        }
        }


        // Collect the stacks that are necessary to be removed instead of performing the removal
        // by looping mStacks, so that we don't miss any stacks after the stack size changed or
        // stacks reordered.
        final ArrayList<ActivityStack> stacks = new ArrayList<>();
        for (int j = activityTypes.length - 1 ; j >= 0; --j) {
        for (int j = activityTypes.length - 1 ; j >= 0; --j) {
            final int activityType = activityTypes[j];
            final int activityType = activityTypes[j];
            for (int i = mStacks.size() - 1; i >= 0; --i) {
            for (int i = mStacks.size() - 1; i >= 0; --i) {
                final ActivityStack stack = mStacks.get(i);
                final ActivityStack stack = mStacks.get(i);
                if (stack.getActivityType() == activityType) {
                if (stack.getActivityType() == activityType) {
                    mRootActivityContainer.mStackSupervisor.removeStack(stack);
                    stacks.add(stack);
                }
                }
            }
            }
        }
        }

        for (int i = stacks.size() - 1; i >= 0; --i) {
            mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
        }
    }
    }


    void onStackWindowingModeChanged(ActivityStack stack) {
    void onStackWindowingModeChanged(ActivityStack stack) {
+59 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,9 @@ import static org.junit.Assert.assertFalse;
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.eq;
import static org.mockito.Mockito.doAnswer;


import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.Presubmit;


@@ -277,4 +280,60 @@ public class ActivityDisplayTests extends ActivityTestsBase {
        assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
        assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
        assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1));
        assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1));
    }
    }

    @Test
    public void testRemoveStackInWindowingModes() {
        removeStackTests(() -> mRootActivityContainer.removeStacksInWindowingModes(
                WINDOWING_MODE_FULLSCREEN));
    }

    @Test
    public void testRemoveStackWithActivityTypes() {
        removeStackTests(
                () -> mRootActivityContainer.removeStacksWithActivityTypes(ACTIVITY_TYPE_STANDARD));
    }

    private void removeStackTests(Runnable runnable) {
        final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
        final ActivityStack stack1 = display.createStack(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, ON_TOP);
        final ActivityStack stack2 = display.createStack(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, ON_TOP);
        final ActivityStack stack3 = display.createStack(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, ON_TOP);
        final ActivityStack stack4 = display.createStack(WINDOWING_MODE_FULLSCREEN,
                ACTIVITY_TYPE_STANDARD, ON_TOP);
        final TaskRecord task1 = new TaskBuilder(mService.mStackSupervisor).setStack(
                stack1).setTaskId(1).build();
        final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor).setStack(
                stack2).setTaskId(2).build();
        final TaskRecord task3 = new TaskBuilder(mService.mStackSupervisor).setStack(
                stack3).setTaskId(3).build();
        final TaskRecord task4 = new TaskBuilder(mService.mStackSupervisor).setStack(
                stack4).setTaskId(4).build();

        // Reordering stacks while removing stacks.
        doAnswer(invocation -> {
            display.positionChildAtTop(stack3, false);
            return true;
        }).when(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(),
                any());

        // Removing stacks from the display while removing stacks.
        doAnswer(invocation -> {
            display.removeChild(stack2);
            return true;
        }).when(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(),
                any());

        runnable.run();
        verify(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(),
                any());
        verify(mSupervisor).removeTaskByIdLocked(eq(task3.taskId), anyBoolean(), anyBoolean(),
                any());
        verify(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(),
                any());
        verify(mSupervisor).removeTaskByIdLocked(eq(task1.taskId), anyBoolean(), anyBoolean(),
                any());
    }
}
}