1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.quickstep; 18 19 import android.content.Context; 20 21 import androidx.annotation.Nullable; 22 23 import com.android.systemui.shared.recents.model.Task; 24 25 import java.util.ArrayList; 26 import java.util.Collections; 27 import java.util.List; 28 import java.util.function.Consumer; 29 30 /** 31 * This class is responsible for maintaining the list of tasks and the task content. The list must 32 * be updated explicitly with {@link #loadTaskList} whenever the list needs to be 33 * up-to-date. 34 */ 35 public final class TaskListLoader { 36 37 private final RecentsModel mRecentsModel; 38 39 private ArrayList<Task> mTaskList = new ArrayList<>(); 40 private int mTaskListChangeId; 41 TaskListLoader(Context context)42 public TaskListLoader(Context context) { 43 mRecentsModel = RecentsModel.INSTANCE.get(context); 44 } 45 46 /** 47 * Returns the current task list as of the last completed load (see {@link #loadTaskList}) as a 48 * read-only list. This list of tasks is not guaranteed to have all content loaded. 49 * 50 * @return the current list of tasks 51 */ getCurrentTaskList()52 public List<Task> getCurrentTaskList() { 53 return Collections.unmodifiableList(mTaskList); 54 } 55 56 /** 57 * Whether or not the loader needs to load data to be up to date. This can return true if the 58 * task list is already up to date OR there is already a load in progress for the task list to 59 * become up to date. 60 * 61 * @return true if already up to date or load in progress, false otherwise 62 */ needsToLoad()63 public boolean needsToLoad() { 64 return !mRecentsModel.isTaskListValid(mTaskListChangeId); 65 } 66 67 /** 68 * Fetches the most recent tasks and updates the task list asynchronously. This call does not 69 * provide guarantees the task content (icon, thumbnail, label) are loaded but will fill in 70 * what it has. May run the callback immediately if there have been no changes in the task 71 * list since the start of the last load. 72 * 73 * @param onLoadedCallback callback to run when task list is loaded 74 */ loadTaskList(@ullable Consumer<ArrayList<Task>> onLoadedCallback)75 public void loadTaskList(@Nullable Consumer<ArrayList<Task>> onLoadedCallback) { 76 if (!needsToLoad()) { 77 if (onLoadedCallback != null) { 78 onLoadedCallback.accept(mTaskList); 79 } 80 return; 81 } 82 // TODO: Look into error checking / more robust handling for when things go wrong. 83 mTaskListChangeId = mRecentsModel.getTasks(loadedTasks -> { 84 ArrayList<Task> tasks = new ArrayList<>(loadedTasks); 85 // Reverse tasks to put most recent at the bottom of the view 86 Collections.reverse(tasks); 87 // Load task content 88 for (Task task : tasks) { 89 int loadedPos = mTaskList.indexOf(task); 90 if (loadedPos == -1) { 91 continue; 92 } 93 Task loadedTask = mTaskList.get(loadedPos); 94 task.icon = loadedTask.icon; 95 task.titleDescription = loadedTask.titleDescription; 96 task.thumbnail = loadedTask.thumbnail; 97 } 98 mTaskList = tasks; 99 onLoadedCallback.accept(tasks); 100 }); 101 } 102 103 /** 104 * Load task icon and label asynchronously if it is not already loaded in the task. If the task 105 * already has an icon, this calls the callback immediately. 106 * 107 * @param task task to update with icon + label 108 * @param onLoadedCallback callback to run when task has icon and label 109 */ loadTaskIconAndLabel(Task task, @Nullable Runnable onLoadedCallback)110 public void loadTaskIconAndLabel(Task task, @Nullable Runnable onLoadedCallback) { 111 mRecentsModel.getIconCache().updateIconInBackground(task, 112 loadedTask -> onLoadedCallback.run()); 113 } 114 115 /** 116 * Load thumbnail asynchronously if not already loaded in the task. If the task already has a 117 * thumbnail or if the thumbnail is cached, this calls the callback immediately. 118 * 119 * @param task task to update with the thumbnail 120 * @param onLoadedCallback callback to run when task has thumbnail 121 */ loadTaskThumbnail(Task task, @Nullable Runnable onLoadedCallback)122 public void loadTaskThumbnail(Task task, @Nullable Runnable onLoadedCallback) { 123 mRecentsModel.getThumbnailCache().updateThumbnailInBackground(task, 124 thumbnail -> onLoadedCallback.run()); 125 } 126 127 /** 128 * Removes the task from the current task list. 129 */ removeTask(Task task)130 void removeTask(Task task) { 131 mTaskList.remove(task); 132 } 133 134 /** 135 * Clears the current task list. 136 */ clearAllTasks()137 void clearAllTasks() { 138 mTaskList.clear(); 139 } 140 } 141