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

Commit 2a4dce14 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fixing loadTasksInBackground called twice on swipe up" into ub-launcher3-rvc-dev

parents 5f1274c8 b3968640
Loading
Loading
Loading
Loading
+55 −28
Original line number Diff line number Diff line
@@ -40,21 +40,20 @@ import java.util.function.Consumer;
/**
 * Manages the recent task list from the system, caching it as necessary.
 */
@TargetApi(Build.VERSION_CODES.P)
@TargetApi(Build.VERSION_CODES.R)
public class RecentTasksList extends TaskStackChangeListener {

    private static final TaskLoadResult INVALID_RESULT = new TaskLoadResult(-1, false, 0);

    private final KeyguardManagerCompat mKeyguardManager;
    private final LooperExecutor mMainThreadExecutor;
    private final ActivityManagerWrapper mActivityManagerWrapper;

    // The list change id, increments as the task list changes in the system
    private int mChangeId;
    // The last change id when the list was last loaded completely, must be <= the list change id
    private int mLastLoadedId;
    // The last change id was loaded with keysOnly  = true
    private boolean mLastLoadHadKeysOnly;

    ArrayList<Task> mTasks = new ArrayList<>();
    private TaskLoadResult mResultsBg = INVALID_RESULT;
    private TaskLoadResult mResultsUi = INVALID_RESULT;

    public RecentTasksList(LooperExecutor mainThreadExecutor,
            KeyguardManagerCompat keyguardManager, ActivityManagerWrapper activityManagerWrapper) {
@@ -71,7 +70,7 @@ public class RecentTasksList extends TaskStackChangeListener {
    public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
        // Kick off task loading in the background
        UI_HELPER_EXECUTOR.execute(() -> {
            ArrayList<Task> tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
            ArrayList<Task> tasks = loadTasksInBackground(numTasks, -1, true /* loadKeysOnly */);
            mMainThreadExecutor.execute(() -> callback.accept(tasks));
        });
    }
@@ -85,26 +84,30 @@ public class RecentTasksList extends TaskStackChangeListener {
     */
    public synchronized int getTasks(boolean loadKeysOnly, Consumer<ArrayList<Task>> callback) {
        final int requestLoadId = mChangeId;
        Runnable resultCallback = callback == null
                ? () -> { }
                : () -> callback.accept(copyOf(mTasks));

        if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
        if (mResultsUi.isValidForRequest(requestLoadId, loadKeysOnly)) {
            // The list is up to date, send the callback on the next frame,
            // so that requestID can be returned first.
            mMainThreadExecutor.post(resultCallback);
            if (callback != null) {
                // Copy synchronously as the changeId might change by next frame
                ArrayList<Task> result = copyOf(mResultsUi);
                mMainThreadExecutor.post(() -> callback.accept(result));
            }

            return requestLoadId;
        }

        // Kick off task loading in the background
        UI_HELPER_EXECUTOR.execute(() -> {
            ArrayList<Task> tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);

            if (!mResultsBg.isValidForRequest(requestLoadId, loadKeysOnly)) {
                mResultsBg = loadTasksInBackground(Integer.MAX_VALUE, requestLoadId, loadKeysOnly);
            }
            TaskLoadResult loadResult = mResultsBg;
            mMainThreadExecutor.execute(() -> {
                mTasks = tasks;
                mLastLoadedId = requestLoadId;
                mLastLoadHadKeysOnly = loadKeysOnly;
                resultCallback.run();
                mResultsUi = loadResult;
                if (callback != null) {
                    ArrayList<Task> result = copyOf(mResultsUi);
                    callback.accept(result);
                }
            });
        });

@@ -119,8 +122,8 @@ public class RecentTasksList extends TaskStackChangeListener {
    }

    @Override
    public synchronized void onTaskStackChanged() {
        mChangeId++;
    public void onTaskStackChanged() {
        invalidateLoadedTasks();
    }

    @Override
@@ -131,22 +134,28 @@ public class RecentTasksList extends TaskStackChangeListener {
        // callback (those are for changes to the active tasks), but the task list is still updated,
        // so we should also invalidate the change id to ensure we load a new list instead of 
        // reusing a stale list.
        mChangeId++;
        invalidateLoadedTasks();
    }

    @Override
    public void onTaskRemoved(int taskId) {
        mTasks = loadTasksInBackground(Integer.MAX_VALUE, false);
        invalidateLoadedTasks();
    }


    @Override
    public synchronized void onActivityPinned(String packageName, int userId, int taskId,
            int stackId) {
        mChangeId++;
    public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
        invalidateLoadedTasks();
    }

    @Override
    public synchronized void onActivityUnpinned() {
        invalidateLoadedTasks();
    }

    private synchronized void invalidateLoadedTasks() {
        UI_HELPER_EXECUTOR.execute(() -> mResultsBg = INVALID_RESULT);
        mResultsUi = INVALID_RESULT;
        mChangeId++;
    }

@@ -154,9 +163,8 @@ public class RecentTasksList extends TaskStackChangeListener {
     * Loads and creates a list of all the recent tasks.
     */
    @VisibleForTesting
    ArrayList<Task> loadTasksInBackground(int numTasks, boolean loadKeysOnly) {
    TaskLoadResult loadTasksInBackground(int numTasks, int requestId, boolean loadKeysOnly) {
        int currentUserId = Process.myUserHandle().getIdentifier();
        ArrayList<Task> allTasks = new ArrayList<>();
        List<ActivityManager.RecentTaskInfo> rawTasks =
                mActivityManagerWrapper.getRecentTasks(numTasks, currentUserId);
        // The raw tasks are given in most-recent to least-recent order, we need to reverse it
@@ -173,6 +181,7 @@ public class RecentTasksList extends TaskStackChangeListener {
            }
        };

        TaskLoadResult allTasks = new TaskLoadResult(requestId, loadKeysOnly, rawTasks.size());
        for (ActivityManager.RecentTaskInfo rawTask : rawTasks) {
            Task.TaskKey taskKey = new Task.TaskKey(rawTask);
            Task task;
@@ -197,4 +206,22 @@ public class RecentTasksList extends TaskStackChangeListener {
        }
        return newTasks;
    }

    private static class TaskLoadResult extends ArrayList<Task> {

        final int mId;

        // If the result was loaded with keysOnly  = true
        final boolean mKeysOnly;

        TaskLoadResult(int id, boolean keysOnly, int size) {
            super(size);
            mId = id;
            mKeysOnly = keysOnly;
        }

        boolean isValidForRequest(int requestId, boolean loadKeysOnly) {
            return mId == requestId && (!mKeysOnly || loadKeysOnly);
        }
    }
}
 No newline at end of file
+4 −4
Original line number Diff line number Diff line
@@ -58,9 +58,9 @@ public class RecentTasksListTest {
    }

    @Test
    public void onTaskRemoved_reloadsAllTasks() {
    public void onTaskRemoved_doesNotFetchTasks() {
        mRecentTasksList.onTaskRemoved(0);
        verify(mockActivityManagerWrapper, times(1))
        verify(mockActivityManagerWrapper, times(0))
                .getRecentTasks(anyInt(), anyInt());
    }

@@ -77,7 +77,7 @@ public class RecentTasksListTest {
        when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
                .thenReturn(Collections.singletonList(recentTaskInfo));

        List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, true);
        List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, -1, true);

        assertEquals(1, taskList.size());
        assertNull(taskList.get(0).taskDescription.getLabel());
@@ -91,7 +91,7 @@ public class RecentTasksListTest {
        when(mockActivityManagerWrapper.getRecentTasks(anyInt(), anyInt()))
                .thenReturn(Collections.singletonList(recentTaskInfo));

        List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, false);
        List<Task> taskList = mRecentTasksList.loadTasksInBackground(Integer.MAX_VALUE, -1, false);

        assertEquals(1, taskList.size());
        assertEquals(taskDescription, taskList.get(0).taskDescription.getLabel());