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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user