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

Commit 92247c0a authored by Louis Chang's avatar Louis Chang
Browse files

Defer sending TaskFragment events while host task is invisible

Or the organizer could start activity or perform unnecessary
actions while in background.

Bug: 204385547
Test: atest TaskFragmentOrganizerControllerTest
Change-Id: I6aa731293d34cd481841a0af2d339a659a148b2e
parent 7d75b594
Loading
Loading
Loading
Loading
+40 −3
Original line number Diff line number Diff line
@@ -434,6 +434,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
        private final TaskFragment mTaskFragment;
        private final IBinder mErrorCallback;
        private final Throwable mException;
        // Set when the event is deferred due to the host task is invisible. The defer time will
        // be the last active time of the host task.
        private long mDeferTime;

        private PendingTaskFragmentEvent(TaskFragment taskFragment,
                ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType) {
@@ -503,11 +506,45 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
                || mPendingTaskFragmentEvents.isEmpty()) {
            return;
        }

        final ArrayList<Task> visibleTasks = new ArrayList<>();
        final ArrayList<Task> invisibleTasks = new ArrayList<>();
        final ArrayList<PendingTaskFragmentEvent> candidateEvents = new ArrayList<>();
        for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) {
            PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
            dispatchEvent(event);
            final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
            final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
            if (task != null && (task.lastActiveTime <= event.mDeferTime
                    || !isTaskVisible(task, visibleTasks, invisibleTasks))) {
                // Defer sending events to the TaskFragment until the host task is active again.
                event.mDeferTime = task.lastActiveTime;
                continue;
            }
            candidateEvents.add(event);
        }
        final int numEvents = candidateEvents.size();
        for (int i = 0; i < numEvents; i++) {
            dispatchEvent(candidateEvents.get(i));
        }
        if (numEvents > 0) {
            mPendingTaskFragmentEvents.removeAll(candidateEvents);
        }
    }

    private static boolean isTaskVisible(Task task, ArrayList<Task> knownVisibleTasks,
            ArrayList<Task> knownInvisibleTasks) {
        if (knownVisibleTasks.contains(task)) {
            return true;
        }
        if (knownInvisibleTasks.contains(task)) {
            return false;
        }
        if (task.shouldBeVisible(null /* starting */)) {
            knownVisibleTasks.add(task);
            return true;
        } else {
            knownInvisibleTasks.add(task);
            return false;
        }
        mPendingTaskFragmentEvents.clear();
    }

    void dispatchPendingInfoChangedEvent(TaskFragment taskFragment) {
+22 −0
Original line number Diff line number Diff line
@@ -424,4 +424,26 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {

        verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
    }

    @Test
    public void testDeferPendingTaskFragmentEventsOfInvisibleTask() {
        // Task - TaskFragment - Activity.
        final Task task = createTask(mDisplayContent);
        final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
                .setParentTask(task)
                .setOrganizer(mOrganizer)
                .build();

        // Mock the task to invisible
        doReturn(false).when(task).shouldBeVisible(any());

        // Sending events
        mController.registerOrganizer(mIOrganizer);
        taskFragment.mTaskFragmentAppearedSent = true;
        mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
        mController.dispatchPendingEvents();

        // Verifies that event was not sent
        verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
    }
}