diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index 607e155d92f6f..bd5df28b76a91 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -16,6 +16,7 @@ package com.android.systemui.recents.misc; +import android.content.Intent; import android.graphics.Color; import android.graphics.Rect; import com.android.systemui.recents.RecentsConfiguration; @@ -93,4 +94,10 @@ public class Utilities { throws IllegalAccessException, InvocationTargetException { sPropertyMethod.invoke(null, property, value); } + + /** Returns whether the specified intent is a document. */ + public static boolean isDocument(Intent intent) { + int flags = intent.getFlags(); + return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT; + } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java index 5f4fabeaa918b..bb4dc760199eb 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java @@ -28,20 +28,20 @@ import java.util.HashMap; public class KeyStoreLruCache { // We keep a set of keys that are associated with the LRU cache, so that we can find out // information about the Task that was previously in the cache. - HashMap mKeys = new HashMap(); + HashMap mTaskKeys = new HashMap(); // The cache implementation - LruCache mCache; + LruCache mCache; public KeyStoreLruCache(int cacheSize) { - mCache = new LruCache(cacheSize) { + mCache = new LruCache(cacheSize) { @Override - protected int sizeOf(Task.TaskKey t, V v) { + protected int sizeOf(Integer taskId, V v) { return computeSize(v); } @Override - protected void entryRemoved(boolean evicted, Task.TaskKey key, V oldV, V newV) { - mKeys.remove(key); + protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) { + mTaskKeys.remove(taskId); } }; } @@ -53,46 +53,41 @@ public class KeyStoreLruCache { /** Gets a specific entry in the cache. */ final V get(Task.TaskKey key) { - return mCache.get(key); + return mCache.get(key.id); } /** - * Returns the value only if the last active time of the key currently in the lru cache is - * greater than or equal to the last active time of the key specified. + * Returns the value only if the Task has not updated since the last time it was in the cache. */ - final V getCheckLastActiveTime(Task.TaskKey key) { - Task.TaskKey lruKey = mKeys.get(key); - if (lruKey != null && (lruKey.lastActiveTime < key.lastActiveTime)) { - // The task has changed (been made active since the last time it was put into the + final V getAndInvalidateIfModified(Task.TaskKey key) { + Task.TaskKey lastKey = mTaskKeys.get(key.id); + if (lastKey != null && (lastKey.lastActiveTime < key.lastActiveTime)) { + // The task has updated (been made active since the last time it was put into the // LRU cache) so invalidate that item in the cache - remove(lruKey); + remove(key); return null; } // Either the task does not exist in the cache, or the last active time is the same as - // the key specified - return mCache.get(key); + // the key specified, so return what is in the cache + return mCache.get(key.id); } /** Puts an entry in the cache for a specific key. */ final void put(Task.TaskKey key, V value) { - mCache.put(key, value); - if (mKeys.containsKey(key)) { - mKeys.get(key).updateLastActiveTime(key.lastActiveTime); - } else { - mKeys.put(key, key); - } + mCache.put(key.id, value); + mTaskKeys.put(key.id, key); } /** Removes a cache entry for a specific key. */ final void remove(Task.TaskKey key) { - mCache.remove(key); - mKeys.remove(key); + mCache.remove(key.id); + mTaskKeys.remove(key.id); } /** Removes all the entries in the cache. */ final void evictAll() { mCache.evictAll(); - mKeys.clear(); + mTaskKeys.clear(); } /** Returns the size of the cache. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index 71979c4f7015a..adf07947144ff 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -31,6 +31,7 @@ import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.SystemServicesProxy; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; @@ -41,6 +42,18 @@ import java.util.concurrent.ConcurrentLinkedQueue; class TaskResourceLoadQueue { ConcurrentLinkedQueue mQueue = new ConcurrentLinkedQueue(); + /** Adds a new task to the load queue */ + void addTasks(Collection tasks) { + for (Task t : tasks) { + if (!mQueue.contains(t)) { + mQueue.add(t); + } + } + synchronized(this) { + notifyAll(); + } + } + /** Adds a new task to the load queue */ void addTask(Task t) { if (!mQueue.contains(t)) { @@ -153,30 +166,30 @@ class TaskResourceLoader implements Runnable { // Load the next item from the queue final Task t = mLoadQueue.nextTask(); if (t != null) { - Drawable cachedIcon = mApplicationIconCache.getCheckLastActiveTime(t.key); - Bitmap cachedThumbnail = mThumbnailCache.getCheckLastActiveTime(t.key); + Drawable cachedIcon = mApplicationIconCache.get(t.key); + Bitmap cachedThumbnail = mThumbnailCache.get(t.key); // Load the application icon if it is stale or we haven't cached one yet if (cachedIcon == null) { - Drawable icon = null; ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(), t.userId); if (info != null) { - icon = ssp.getActivityIcon(info, t.userId); + cachedIcon = ssp.getActivityIcon(info, t.userId); } - // If we can't load the icon, then set the default application icon into the - // cache. This will remain until the task's last active time is updated. - cachedIcon = icon != null ? icon : mDefaultApplicationIcon; + if (cachedIcon == null) { + cachedIcon = mDefaultApplicationIcon; + } + // At this point, even if we can't load the icon, we will set the default + // icon. mApplicationIconCache.put(t.key, cachedIcon); } // Load the thumbnail if it is stale or we haven't cached one yet if (cachedThumbnail == null) { - Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id); - if (thumbnail != null) { - thumbnail.setHasAlpha(false); + cachedThumbnail = ssp.getTaskThumbnail(t.key.id); + if (cachedThumbnail != null) { + cachedThumbnail.setHasAlpha(false); + } else { + cachedThumbnail = mDefaultThumbnail; } - // Even if we can't load the icon, we set the default thumbnail into the - // cache. This will remain until the task's last active time is updated. - cachedThumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail; mThumbnailCache.put(t.key, cachedThumbnail); } if (!mCancelled) { @@ -281,11 +294,11 @@ public class RecentsTaskLoader { return mSystemServicesProxy; } + /** Gets the list of recent tasks, ordered from back to front. */ private static List getRecentTasks(SystemServicesProxy ssp) { List tasks = ssp.getRecentTasks(50, UserHandle.CURRENT.getIdentifier()); Collections.reverse(tasks); - return tasks; } @@ -302,7 +315,7 @@ public class RecentsTaskLoader { SystemServicesProxy ssp = mSystemServicesProxy; List tasks = getRecentTasks(ssp); - // Add each task to the task stack + // From back to front, add each task to the task stack int taskCount = tasks.size(); for (int i = 0; i < taskCount; i++) { ActivityManager.RecentTaskInfo t = tasks.get(i); @@ -311,7 +324,7 @@ public class RecentsTaskLoader { ActivityManager.TaskDescription av = t.taskDescription; String activityLabel = null; - Drawable activityIcon = null; + Drawable activityIcon = mDefaultApplicationIcon; int activityColor = config.taskBarViewDefaultBackgroundColor; if (av != null) { activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info)); @@ -323,7 +336,6 @@ public class RecentsTaskLoader { } else { activityLabel = ssp.getActivityLabel(info); } - boolean isForemostTask = (i == (taskCount - 1)); // Create a new task Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, t.affiliatedTaskId, @@ -333,44 +345,35 @@ public class RecentsTaskLoader { // Preload the specified number of apps if (i >= (taskCount - preloadCount)) { // Load the icon from the cache if possible - task.applicationIcon = mApplicationIconCache.getCheckLastActiveTime(task.key); + task.applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(task.key); if (task.applicationIcon == null) { - if (isForemostTask) { - // We force loading the application icon for the foremost task - task.applicationIcon = ssp.getActivityIcon(info, task.userId); - if (task.applicationIcon == null) { - task.applicationIcon = mDefaultApplicationIcon; - } - // Even if we can't load the icon we set the default application icon into - // the cache. This will remain until the task's last active time is updated. + // Load the icon from the system + task.applicationIcon = ssp.getActivityIcon(info, task.userId); + if (task.applicationIcon != null) { mApplicationIconCache.put(task.key, task.applicationIcon); - } else { - // Either the task has changed since the last active time, or it was not - // previously cached, so try and load the task anew. - tasksToLoad.add(task); } } + if (task.applicationIcon == null) { + // Either the task has changed since the last active time, or it was not + // previously cached, so try and load the task anew. + tasksToLoad.add(task); + } - // Load the thumbnail (if possible and not the foremost task, from the cache) - task.thumbnail = mThumbnailCache.getCheckLastActiveTime(task.key); + // Load the thumbnail from the cache if possible + task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(task.key); if (task.thumbnail == null) { - if (isForemostTask) { - // We force loading the thumbnail icon for the foremost task - task.thumbnail = ssp.getTaskThumbnail(task.key.id); - if (task.thumbnail != null) { - task.thumbnail.setHasAlpha(false); - } else { - task.thumbnail = mDefaultThumbnail; - } - // Even if we can't load the thumbnail we set the default thumbnail into - // the cache. This will remain until the task's last active time is updated. + // Load the thumbnail from the system + task.thumbnail = ssp.getTaskThumbnail(task.key.id); + if (task.thumbnail != null) { + task.thumbnail.setHasAlpha(false); mThumbnailCache.put(task.key, task.thumbnail); - } else { - // Either the task has changed since the last active time, or it was not - // previously cached, so try and load the task anew. - tasksToLoad.add(task); } } + if (task.thumbnail == null) { + // Either the task has changed since the last active time, or it was not + // previously cached, so try and load the task anew. + tasksToLoad.add(task); + } } // Add the task to the stack @@ -380,13 +383,9 @@ public class RecentsTaskLoader { // Simulate the groupings that we describe stack.createAffiliatedGroupings(); - // Start the task loader + // Start the task loader and add all the tasks we need to load mLoader.start(context); - - // Add all the tasks that we are reloading - for (Task t : tasksToLoad) { - mLoadQueue.addTask(t); - } + mLoadQueue.addTasks(tasksToLoad); // Update the package monitor with the list of packages to listen for mPackageMonitor.setTasks(tasks); @@ -414,18 +413,14 @@ public class RecentsTaskLoader { /** Acquires the task resource data directly from the pool. */ public void loadTaskData(Task t) { - Drawable applicationIcon = mApplicationIconCache.get(t.key); - Bitmap thumbnail = mThumbnailCache.get(t.key); + Drawable applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(t.key); + Bitmap thumbnail = mThumbnailCache.getAndInvalidateIfModified(t.key); - boolean requiresLoad = false; - if (applicationIcon == null) { - applicationIcon = mDefaultApplicationIcon; - requiresLoad = true; - } - if (thumbnail == null) { - thumbnail = mLoadingThumbnail; - requiresLoad = true; - } + // Grab the thumbnail/icon from the cache, if either don't exist, then trigger a reload and + // use the default assets in their place until they load + boolean requiresLoad = (applicationIcon == null) || (thumbnail == null); + applicationIcon = applicationIcon != null ? applicationIcon : mDefaultApplicationIcon; + thumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail; if (requiresLoad) { mLoadQueue.addTask(t); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java index 1670735873048..24733526eb6b0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -51,10 +51,6 @@ public class Task { this.lastActiveTime = lastActiveTime; } - public void updateLastActiveTime(long lastActiveTime) { - this.lastActiveTime = lastActiveTime; - } - @Override public boolean equals(Object o) { if (!(o instanceof TaskKey)) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 78a99e06c2866..e1c652e69377c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -38,6 +38,7 @@ import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.SystemServicesProxy; +import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.RecentsPackageMonitor; import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.SpaceNode; @@ -458,7 +459,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV Intent i = new Intent(task.key.baseIntent); i.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | Intent.FLAG_ACTIVITY_TASK_ON_HOME); - if ((i.getFlags() & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == 0) { + if (!Utilities.isDocument(i)) { i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } try { @@ -510,11 +511,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV loader.deleteTaskData(t, false); // Remove the old task from activity manager - int flags = t.key.baseIntent.getFlags(); - boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == - Intent.FLAG_ACTIVITY_NEW_DOCUMENT; RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id, - isDocument); + Utilities.isDocument(t.key.baseIntent)); } @Override