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

This commit is contained in:
TreeHugger Robot
2020-06-01 22:44:03 +00:00
committed by Android (Google) Code Review
2 changed files with 59 additions and 32 deletions

View File

@@ -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);
}
}
}

View File

@@ -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());