RecentsTaskLoadPlan.java revision 96d704186621f6310e0e7d39db57caff67baa96c
1/* 2 * Copyright (C) 2014 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 17package com.android.systemui.recents.model; 18 19import android.app.ActivityManager; 20import android.content.Context; 21import android.content.res.Resources; 22import android.graphics.Bitmap; 23import android.graphics.drawable.Drawable; 24import android.os.UserHandle; 25import android.util.Log; 26import com.android.systemui.recents.RecentsConfiguration; 27import com.android.systemui.recents.misc.SystemServicesProxy; 28 29import java.util.ArrayList; 30import java.util.Collections; 31import java.util.HashMap; 32import java.util.List; 33 34 35/** 36 * This class stores the loading state as it goes through multiple stages of loading: 37 * - preloadRawTasks() will load the raw set of recents tasks from the system 38 * - preloadPlan() will construct a new task stack with all metadata and only icons and thumbnails 39 * that are currently in the cache 40 * - executePlan() will actually load and fill in the icons and thumbnails according to the load 41 * options specified, such that we can transition into the Recents activity seamlessly 42 */ 43public class RecentsTaskLoadPlan { 44 static String TAG = "RecentsTaskLoadPlan"; 45 static boolean DEBUG = false; 46 47 /** The set of conditions to load tasks. */ 48 public static class Options { 49 public int runningTaskId = -1; 50 public boolean loadIcons = true; 51 public boolean loadThumbnails = true; 52 public boolean onlyLoadForCache = false; 53 public int numVisibleTasks = 0; 54 public int numVisibleTaskThumbnails = 0; 55 } 56 57 Context mContext; 58 RecentsConfiguration mConfig; 59 SystemServicesProxy mSystemServicesProxy; 60 61 List<ActivityManager.RecentTaskInfo> mRawTasks; 62 TaskStack mStack; 63 HashMap<Task.ComponentNameKey, ActivityInfoHandle> mActivityInfoCache = 64 new HashMap<Task.ComponentNameKey, ActivityInfoHandle>(); 65 66 /** Package level ctor */ 67 RecentsTaskLoadPlan(Context context, RecentsConfiguration config, SystemServicesProxy ssp) { 68 mContext = context; 69 mConfig = config; 70 mSystemServicesProxy = ssp; 71 } 72 73 /** 74 * An optimization to preload the raw list of tasks. 75 */ 76 public synchronized void preloadRawTasks(boolean isTopTaskHome) { 77 mRawTasks = mSystemServicesProxy.getRecentTasks(mConfig.maxNumTasksToLoad, 78 UserHandle.CURRENT.getIdentifier(), isTopTaskHome); 79 Collections.reverse(mRawTasks); 80 81 if (DEBUG) Log.d(TAG, "preloadRawTasks, tasks: " + mRawTasks.size()); 82 } 83 84 /** 85 * Preloads the list of recent tasks from the system. After this call, the TaskStack will 86 * have a list of all the recent tasks with their metadata, not including icons or 87 * thumbnails which were not cached and have to be loaded. 88 */ 89 synchronized void preloadPlan(RecentsTaskLoader loader, boolean isTopTaskHome) { 90 if (DEBUG) Log.d(TAG, "preloadPlan"); 91 92 mActivityInfoCache.clear(); 93 mStack = new TaskStack(); 94 95 Resources res = mContext.getResources(); 96 ArrayList<Task> loadedTasks = new ArrayList<Task>(); 97 if (mRawTasks == null) { 98 preloadRawTasks(isTopTaskHome); 99 } 100 int taskCount = mRawTasks.size(); 101 for (int i = 0; i < taskCount; i++) { 102 ActivityManager.RecentTaskInfo t = mRawTasks.get(i); 103 104 // Compose the task key 105 Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId, 106 t.firstActiveTime, t.lastActiveTime); 107 108 // Get an existing activity info handle if possible 109 Task.ComponentNameKey cnKey = taskKey.getComponentNameKey(); 110 ActivityInfoHandle infoHandle; 111 boolean hadCachedActivityInfo = false; 112 if (mActivityInfoCache.containsKey(cnKey)) { 113 infoHandle = mActivityInfoCache.get(cnKey); 114 hadCachedActivityInfo = true; 115 } else { 116 infoHandle = new ActivityInfoHandle(); 117 } 118 119 // Load the label, icon, and color 120 String activityLabel = loader.getAndUpdateActivityLabel(taskKey, t.taskDescription, 121 mSystemServicesProxy, infoHandle); 122 Drawable activityIcon = loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, 123 mSystemServicesProxy, res, infoHandle, false); 124 int activityColor = loader.getActivityPrimaryColor(t.taskDescription, mConfig); 125 126 // Update the activity info cache 127 if (!hadCachedActivityInfo && infoHandle.info != null) { 128 mActivityInfoCache.put(cnKey, infoHandle); 129 } 130 131 Bitmap icon = t.taskDescription != null 132 ? t.taskDescription.getInMemoryIcon() 133 : null; 134 String iconFilename = t.taskDescription != null 135 ? t.taskDescription.getIconFilename() 136 : null; 137 138 // Add the task to the stack 139 Task task = new Task(taskKey, (t.id != RecentsTaskLoader.INVALID_TASK_ID), 140 t.affiliatedTaskId, t.affiliatedTaskColor, activityLabel, activityIcon, 141 activityColor, (i == (taskCount - 1)), mConfig.lockToAppEnabled, icon, 142 iconFilename); 143 task.thumbnail = loader.getAndUpdateThumbnail(taskKey, mSystemServicesProxy, false); 144 loadedTasks.add(task); 145 } 146 mStack.setTasks(loadedTasks); 147 mStack.createAffiliatedGroupings(mConfig); 148 149 // Assertion 150 if (mStack.getTaskCount() != mRawTasks.size()) { 151 throw new RuntimeException("Loading failed"); 152 } 153 } 154 155 /** 156 * Called to apply the actual loading based on the specified conditions. 157 */ 158 synchronized void executePlan(Options opts, RecentsTaskLoader loader, 159 TaskResourceLoadQueue loadQueue) { 160 if (DEBUG) Log.d(TAG, "executePlan, # tasks: " + opts.numVisibleTasks + 161 ", # thumbnails: " + opts.numVisibleTaskThumbnails + 162 ", running task id: " + opts.runningTaskId); 163 164 Resources res = mContext.getResources(); 165 166 // Iterate through each of the tasks and load them according to the load conditions. 167 ArrayList<Task> tasks = mStack.getTasks(); 168 int taskCount = tasks.size(); 169 for (int i = 0; i < taskCount; i++) { 170 ActivityManager.RecentTaskInfo t = mRawTasks.get(i); 171 Task task = tasks.get(i); 172 Task.TaskKey taskKey = task.key; 173 174 // Get an existing activity info handle if possible 175 Task.ComponentNameKey cnKey = taskKey.getComponentNameKey(); 176 ActivityInfoHandle infoHandle; 177 boolean hadCachedActivityInfo = false; 178 if (mActivityInfoCache.containsKey(cnKey)) { 179 infoHandle = mActivityInfoCache.get(cnKey); 180 hadCachedActivityInfo = true; 181 } else { 182 infoHandle = new ActivityInfoHandle(); 183 } 184 185 boolean isRunningTask = (task.key.id == opts.runningTaskId); 186 boolean isVisibleTask = i >= (taskCount - opts.numVisibleTasks); 187 boolean isVisibleThumbnail = i >= (taskCount - opts.numVisibleTaskThumbnails); 188 189 if (opts.loadIcons && (isRunningTask || isVisibleTask)) { 190 if (task.activityIcon == null) { 191 if (DEBUG) Log.d(TAG, "\tLoading icon: " + taskKey); 192 task.activityIcon = loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, 193 mSystemServicesProxy, res, infoHandle, true); 194 } 195 } 196 if (opts.loadThumbnails && (isRunningTask || isVisibleThumbnail)) { 197 if (task.thumbnail == null) { 198 if (DEBUG) Log.d(TAG, "\tLoading thumbnail: " + taskKey); 199 if (mConfig.svelteLevel <= RecentsConfiguration.SVELTE_LIMIT_CACHE) { 200 task.thumbnail = loader.getAndUpdateThumbnail(taskKey, mSystemServicesProxy, 201 true); 202 } else if (mConfig.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) { 203 loadQueue.addTask(task); 204 } 205 } 206 } 207 208 // Update the activity info cache 209 if (!hadCachedActivityInfo && infoHandle.info != null) { 210 mActivityInfoCache.put(cnKey, infoHandle); 211 } 212 } 213 } 214 215 /** 216 * Composes and returns a TaskStack from the preloaded list of recent tasks. 217 */ 218 public TaskStack getTaskStack() { 219 return mStack; 220 } 221 222 /** 223 * Composes and returns a SpaceNode from the preloaded list of recent tasks. 224 */ 225 public SpaceNode getSpaceNode() { 226 SpaceNode node = new SpaceNode(); 227 node.setStack(mStack); 228 return node; 229 } 230} 231