am 2a2b956e: am 3bf3d3c0: Merge "Fixing optimization in Task loading. (Bug 16372369)" into lmp-dev

* commit '2a2b956e3f405b91fb2fdcaabc663a799dec69b2':
  Fixing optimization in Task loading. (Bug 16372369)
This commit is contained in:
Winson Chung
2014-07-17 20:59:26 +00:00
committed by Android Git Automerger
5 changed files with 88 additions and 97 deletions

View File

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

View File

@@ -28,20 +28,20 @@ import java.util.HashMap;
public class KeyStoreLruCache<V> {
// 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<Task.TaskKey, Task.TaskKey> mKeys = new HashMap<Task.TaskKey, Task.TaskKey>();
HashMap<Integer, Task.TaskKey> mTaskKeys = new HashMap<Integer, Task.TaskKey>();
// The cache implementation
LruCache<Task.TaskKey, V> mCache;
LruCache<Integer, V> mCache;
public KeyStoreLruCache(int cacheSize) {
mCache = new LruCache<Task.TaskKey, V>(cacheSize) {
mCache = new LruCache<Integer, V>(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<V> {
/** 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. */

View File

@@ -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<Task> mQueue = new ConcurrentLinkedQueue<Task>();
/** Adds a new task to the load queue */
void addTasks(Collection<Task> 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<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp) {
List<ActivityManager.RecentTaskInfo> tasks =
ssp.getRecentTasks(50, UserHandle.CURRENT.getIdentifier());
Collections.reverse(tasks);
return tasks;
}
@@ -302,7 +315,7 @@ public class RecentsTaskLoader {
SystemServicesProxy ssp = mSystemServicesProxy;
List<ActivityManager.RecentTaskInfo> 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);
}

View File

@@ -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)) {

View File

@@ -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