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

Commit dfb4a448 authored by Louis Chang's avatar Louis Chang Committed by Android (Google) Code Review
Browse files

Merge "[2/n] Pin ActivityStack" into udc-qpr-dev

parents 7b933759 44d6c6c2
Loading
Loading
Loading
Loading
+17 −11
Original line number Diff line number Diff line
@@ -308,7 +308,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen

            forAllTaskContainers(taskContainer -> {
                synchronized (mLock) {
                    final List<TaskFragmentContainer> containers = taskContainer.mContainers;
                    final List<TaskFragmentContainer> containers =
                            taskContainer.getTaskFragmentContainers();
                    // Clean up the TaskFragmentContainers by the z-order from the lowest.
                    for (int i = 0; i < containers.size(); i++) {
                        final TaskFragmentContainer container = containers.get(i);
@@ -611,8 +612,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
            @NonNull TaskContainer taskContainer) {
        // Update all TaskFragments in the Task. Make a copy of the list since some may be
        // removed on updating.
        final List<TaskFragmentContainer> containers =
                new ArrayList<>(taskContainer.mContainers);
        final List<TaskFragmentContainer> containers = taskContainer.getTaskFragmentContainers();
        for (int i = containers.size() - 1; i >= 0; i--) {
            final TaskFragmentContainer container = containers.get(i);
            // Wait until onTaskFragmentAppeared to update new container.
@@ -1331,7 +1331,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        // Check pending appeared activity first because there can be a delay for the server
        // update.
        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
                    .getTaskFragmentContainers();
            for (int j = containers.size() - 1; j >= 0; j--) {
                final TaskFragmentContainer container = containers.get(j);
                if (container.hasPendingAppearedActivity(activityToken)) {
@@ -1342,7 +1343,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen

        // Check appeared activity if there is no such pending appeared activity.
        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
                    .getTaskFragmentContainers();
            for (int j = containers.size() - 1; j >= 0; j--) {
                final TaskFragmentContainer container = containers.get(j);
                if (container.hasAppearedActivity(activityToken)) {
@@ -1472,7 +1474,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    void removeContainers(@NonNull TaskContainer taskContainer,
            @NonNull List<TaskFragmentContainer> containers) {
        // Remove all split containers that included this one
        taskContainer.mContainers.removeAll(containers);
        taskContainer.removeTaskFragmentContainers(containers);
        // Marked as a pending removal which will be removed after it is actually removed on the
        // server side (#onTaskFragmentVanished).
        // In this way, we can keep track of the Task bounds until we no longer have any
@@ -1497,7 +1499,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        taskContainer.removeSplitContainers(containersToRemove);

        // Cleanup any dependent references.
        for (TaskFragmentContainer containerToUpdate : taskContainer.mContainers) {
        final List<TaskFragmentContainer> taskFragmentContainers =
                taskContainer.getTaskFragmentContainers();
        for (TaskFragmentContainer containerToUpdate : taskFragmentContainers) {
            containerToUpdate.removeContainersToFinishOnExit(containers);
        }
    }
@@ -1536,8 +1540,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
        if (taskContainer == null) {
            return null;
        }
        for (int i = taskContainer.mContainers.size() - 1; i >= 0; i--) {
            final TaskFragmentContainer container = taskContainer.mContainers.get(i);
        final List<TaskFragmentContainer> containers = taskContainer.getTaskFragmentContainers();
        for (int i = containers.size() - 1; i >= 0; i--) {
            final TaskFragmentContainer container = containers.get(i);
            if (!container.isFinished() && (container.getRunningActivityCount() > 0
                    // We may be waiting for the top TaskFragment to become non-empty after
                    // creation. In that case, we don't want to treat the TaskFragment below it as
@@ -1933,7 +1938,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
    @GuardedBy("mLock")
    TaskFragmentContainer getContainer(@NonNull IBinder fragmentToken) {
        for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i).mContainers;
            final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
                    .getTaskFragmentContainers();
            for (TaskFragmentContainer container : containers) {
                if (container.getTaskFragmentToken().equals(fragmentToken)) {
                    return container;
@@ -2094,7 +2100,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
                }
                for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
                    final List<TaskFragmentContainer> containers = mTaskContainers.valueAt(i)
                            .mContainers;
                            .getTaskFragmentContainers();
                    for (int j = containers.size() - 1; j >= 0; j--) {
                        final TaskFragmentContainer container = containers.get(j);
                        if (!container.hasActivity(activityToken)
+36 −2
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ class TaskContainer {

    /** Active TaskFragments in this Task. */
    @NonNull
    final List<TaskFragmentContainer> mContainers = new ArrayList<>();
    private final List<TaskFragmentContainer> mContainers = new ArrayList<>();

    /** Active split pairs in this Task. */
    @NonNull
@@ -207,9 +207,13 @@ class TaskContainer {
        return false;
    }

    /**
     * Returns a list of {@link SplitContainer}. Do not modify the containers directly on the
     * returned list. Use {@link #addSplitContainer} or {@link #removeSplitContainers} instead.
     */
    @NonNull
    List<SplitContainer> getSplitContainers() {
        return new ArrayList<>(mSplitContainers);
        return mSplitContainers;
    }

    void addSplitContainer(@NonNull SplitContainer splitContainer) {
@@ -220,6 +224,36 @@ class TaskContainer {
        mSplitContainers.removeAll(containers);
    }

    void addTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
        mContainers.add(taskFragmentContainer);
    }

    void addTaskFragmentContainer(int index, @NonNull TaskFragmentContainer taskFragmentContainer) {
        mContainers.add(index, taskFragmentContainer);
    }

    void removeTaskFragmentContainer(@NonNull TaskFragmentContainer taskFragmentContainer) {
        mContainers.remove(taskFragmentContainer);
    }

    void removeTaskFragmentContainers(@NonNull List<TaskFragmentContainer> taskFragmentContainer) {
        mContainers.removeAll(taskFragmentContainer);
    }

    void clearTaskFragmentContainer() {
        mContainers.clear();
    }

    /**
     * Returns a list of {@link TaskFragmentContainer}. Do not modify the containers directly on
     * the returned list. Use {@link #addTaskFragmentContainer},
     * {@link #removeTaskFragmentContainer} or other related methods instead.
     */
    @NonNull
    List<TaskFragmentContainer> getTaskFragmentContainers() {
        return mContainers;
    }

    /** Adds the descriptors of split states in this Task to {@code outSplitStates}. */
    void getSplitStates(@NonNull List<SplitInfo> outSplitStates) {
        for (SplitContainer container : mSplitContainers) {
+8 −6
Original line number Diff line number Diff line
@@ -180,23 +180,25 @@ class TaskFragmentContainer {
                throw new IllegalArgumentException(
                        "pairedPrimaryContainer must be in the same Task");
            }
            final int primaryIndex = taskContainer.mContainers.indexOf(pairedPrimaryContainer);
            taskContainer.mContainers.add(primaryIndex + 1, this);
            final int primaryIndex = taskContainer.indexOf(pairedPrimaryContainer);
            taskContainer.addTaskFragmentContainer(primaryIndex + 1, this);
        } else if (pendingAppearedActivity != null) {
            // The TaskFragment will be positioned right above the pending appeared Activity. If any
            // existing TaskFragment is empty with pending Intent, it is likely that the Activity of
            // the pending Intent hasn't been created yet, so the new Activity should be below the
            // empty TaskFragment.
            int i = taskContainer.mContainers.size() - 1;
            final List<TaskFragmentContainer> containers =
                    taskContainer.getTaskFragmentContainers();
            int i = containers.size() - 1;
            for (; i >= 0; i--) {
                final TaskFragmentContainer container = taskContainer.mContainers.get(i);
                final TaskFragmentContainer container = containers.get(i);
                if (!container.isEmpty() || container.getPendingAppearedIntent() == null) {
                    break;
                }
            }
            taskContainer.mContainers.add(i + 1, this);
            taskContainer.addTaskFragmentContainer(i + 1, this);
        } else {
            taskContainer.mContainers.add(this);
            taskContainer.addTaskFragmentContainer(this);
        }
        if (pendingAppearedActivity != null) {
            addPendingAppearedActivity(pendingAppearedActivity);
+13 −16
Original line number Diff line number Diff line
@@ -183,23 +183,23 @@ public class SplitControllerTest {
        // tf2 has running activity so is active.
        final TaskFragmentContainer tf2 = mock(TaskFragmentContainer.class);
        doReturn(1).when(tf2).getRunningActivityCount();
        taskContainer.mContainers.add(tf2);
        taskContainer.addTaskFragmentContainer(tf2);
        // tf3 is finished so is not active.
        final TaskFragmentContainer tf3 = mock(TaskFragmentContainer.class);
        doReturn(true).when(tf3).isFinished();
        doReturn(false).when(tf3).isWaitingActivityAppear();
        taskContainer.mContainers.add(tf3);
        taskContainer.addTaskFragmentContainer(tf3);
        mSplitController.mTaskContainers.put(TASK_ID, taskContainer);

        assertWithMessage("Must return tf2 because tf3 is not active.")
                .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf2);

        taskContainer.mContainers.remove(tf3);
        taskContainer.removeTaskFragmentContainer(tf3);

        assertWithMessage("Must return tf2 because tf2 has running activity.")
                .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf2);

        taskContainer.mContainers.remove(tf2);
        taskContainer.removeTaskFragmentContainer(tf2);

        assertWithMessage("Must return tf because we are waiting for tf1 to appear.")
                .that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf1);
@@ -365,7 +365,8 @@ public class SplitControllerTest {
        final Activity r1 = createMockActivity();
        addSplitTaskFragments(r0, r1);
        final TaskContainer taskContainer = mSplitController.getTaskContainer(TASK_ID);
        final TaskFragmentContainer taskFragmentContainer = taskContainer.mContainers.get(0);
        final TaskFragmentContainer taskFragmentContainer =
                taskContainer.getTaskFragmentContainers().get(0);
        spyOn(taskContainer);

        // No update when the Task is invisible.
@@ -1092,7 +1093,7 @@ public class SplitControllerTest {
        verify(mTransaction).finishActivity(mActivity.getActivityToken());
        verify(mTransaction).finishActivity(secondaryActivity0.getActivityToken());
        verify(mTransaction).finishActivity(secondaryActivity1.getActivityToken());
        assertTrue(taskContainer.mContainers.isEmpty());
        assertTrue(taskContainer.getTaskFragmentContainers().isEmpty());
        assertTrue(taskContainer.getSplitContainers().isEmpty());
    }

@@ -1365,15 +1366,13 @@ public class SplitControllerTest {
        TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
        tf.setInfo(mTransaction, createMockTaskFragmentInfo(tf, mActivity));

        List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
                .mContainers;

        assertEquals(containers.get(0), tf);
        final TaskContainer taskContainer = mSplitController.mTaskContainers.get(TASK_ID);
        assertEquals(taskContainer.getTaskFragmentContainers().get(0), tf);

        mSplitController.finishActivityStacks(Collections.singleton(tf.getTaskFragmentToken()));

        verify(mSplitPresenter).deleteTaskFragment(any(), eq(tf.getTaskFragmentToken()));
        assertTrue(containers.isEmpty());
        assertTrue(taskContainer.getTaskFragmentContainers().isEmpty());
    }

    @Test
@@ -1383,10 +1382,8 @@ public class SplitControllerTest {
        bottomTf.setInfo(mTransaction, createMockTaskFragmentInfo(bottomTf, mActivity));
        topTf.setInfo(mTransaction, createMockTaskFragmentInfo(topTf, createMockActivity()));

        List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
                .mContainers;

        assertEquals(containers.size(), 2);
        final TaskContainer taskContainer = mSplitController.mTaskContainers.get(TASK_ID);
        assertEquals(taskContainer.getTaskFragmentContainers().size(), 2);

        Set<IBinder> activityStackTokens = new ArraySet<>(new IBinder[]{
                topTf.getTaskFragmentToken(), bottomTf.getTaskFragmentToken()});
@@ -1405,7 +1402,7 @@ public class SplitControllerTest {
                        + "regardless of the order in ActivityStack set",
                topTf.getTaskFragmentToken(), fragmentTokens.get(1));

        assertTrue(containers.isEmpty());
        assertTrue(taskContainer.getTaskFragmentContainers().isEmpty());
    }

    @Test
+3 −3
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ public class TaskContainerTest {
        assertFalse(taskContainer.isEmpty());

        taskContainer.mFinishedContainer.add(tf.getTaskFragmentToken());
        taskContainer.mContainers.clear();
        taskContainer.clearTaskFragmentContainer();

        assertFalse(taskContainer.isEmpty());
    }
@@ -152,13 +152,13 @@ public class TaskContainerTest {
        assertNull(taskContainer.getTopNonFinishingActivity());

        final TaskFragmentContainer tf0 = mock(TaskFragmentContainer.class);
        taskContainer.mContainers.add(tf0);
        taskContainer.addTaskFragmentContainer(tf0);
        final Activity activity0 = mock(Activity.class);
        doReturn(activity0).when(tf0).getTopNonFinishingActivity();
        assertEquals(activity0, taskContainer.getTopNonFinishingActivity());

        final TaskFragmentContainer tf1 = mock(TaskFragmentContainer.class);
        taskContainer.mContainers.add(tf1);
        taskContainer.addTaskFragmentContainer(tf1);
        assertEquals(activity0, taskContainer.getTopNonFinishingActivity());

        final Activity activity1 = mock(Activity.class);