Merge "Adding system service proxy to help test UI/performance."
This commit is contained in:
@@ -23,35 +23,26 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.RecentsComponent;
|
||||
import com.android.systemui.SystemUI;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -113,6 +104,7 @@ public class AlternateRecentsComponent {
|
||||
final static String sRecentsService = "com.android.systemui.recents.RecentsService";
|
||||
|
||||
Context mContext;
|
||||
SystemServicesProxy mSystemServicesProxy;
|
||||
|
||||
// Recents service binding
|
||||
Messenger mService = null;
|
||||
@@ -127,6 +119,7 @@ public class AlternateRecentsComponent {
|
||||
|
||||
public AlternateRecentsComponent(Context context) {
|
||||
mContext = context;
|
||||
mSystemServicesProxy = new SystemServicesProxy(context);
|
||||
mMessenger = new Messenger(new RecentsMessageHandler());
|
||||
}
|
||||
|
||||
@@ -219,17 +212,16 @@ public class AlternateRecentsComponent {
|
||||
|
||||
/** Loads the first task thumbnail */
|
||||
Bitmap loadFirstTaskThumbnail() {
|
||||
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
|
||||
ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES,
|
||||
SystemServicesProxy ssp = mSystemServicesProxy;
|
||||
List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
|
||||
UserHandle.CURRENT.getIdentifier());
|
||||
for (ActivityManager.RecentTaskInfo t : tasks) {
|
||||
// Skip tasks in the home stack
|
||||
if (am.isInHomeStack(t.persistentId)) {
|
||||
if (ssp.isInHomeStack(t.persistentId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bitmap thumbnail = am.getTaskTopThumbnail(t.persistentId);
|
||||
Bitmap thumbnail = ssp.getTaskThumbnail(t.persistentId);
|
||||
return thumbnail;
|
||||
}
|
||||
return null;
|
||||
@@ -237,13 +229,12 @@ public class AlternateRecentsComponent {
|
||||
|
||||
/** Returns whether there is a first task */
|
||||
boolean hasFirstTask() {
|
||||
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
|
||||
ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES,
|
||||
SystemServicesProxy ssp = mSystemServicesProxy;
|
||||
List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
|
||||
UserHandle.CURRENT.getIdentifier());
|
||||
for (ActivityManager.RecentTaskInfo t : tasks) {
|
||||
// Skip tasks in the home stack
|
||||
if (am.isInHomeStack(t.persistentId)) {
|
||||
if (ssp.isInHomeStack(t.persistentId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -294,8 +285,8 @@ public class AlternateRecentsComponent {
|
||||
|
||||
// If Recents is the front most activity, then we should just communicate with it directly
|
||||
// to launch the first task or dismiss itself
|
||||
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
|
||||
SystemServicesProxy ssp = mSystemServicesProxy;
|
||||
List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
|
||||
if (!tasks.isEmpty()) {
|
||||
ComponentName topActivity = tasks.get(0).topActivity;
|
||||
|
||||
|
||||
@@ -31,6 +31,12 @@ public class Constants {
|
||||
public static final boolean EnableToggleNewRecentsActivity = false;
|
||||
// This disables the bitmap and icon caches to
|
||||
public static final boolean DisableBackgroundCache = false;
|
||||
// For debugging, this enables us to create mock recents tasks
|
||||
public static final boolean EnableSystemServicesProxy = false;
|
||||
// For debugging, this defines the number of mock recents packages to create
|
||||
public static final int SystemServicesProxyMockPackageCount = 12;
|
||||
// For debugging, this defines the number of mock recents tasks to create
|
||||
public static final int SystemServicesProxyMockTaskCount = 75;
|
||||
|
||||
// Timing certain paths
|
||||
public static final String TimeRecentsStartupKey = "startup";
|
||||
@@ -73,8 +79,6 @@ public class Constants {
|
||||
public static class RecentsTaskLoader {
|
||||
// XXX: This should be calculated on the first load
|
||||
public static final int PreloadFirstTasksCount = 5;
|
||||
// For debugging, this allows us to multiply the number of cards for each task
|
||||
public static final int TaskEntryMultiplier = 1;
|
||||
}
|
||||
|
||||
public static class TaskStackView {
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemService;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.app.ActivityManager;
|
||||
import android.content.ComponentCallbacks2;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
@@ -109,6 +108,7 @@ class TaskResourceLoader implements Runnable {
|
||||
Handler mLoadThreadHandler;
|
||||
Handler mMainThreadHandler;
|
||||
|
||||
SystemServicesProxy mSystemServicesProxy;
|
||||
TaskResourceLoadQueue mLoadQueue;
|
||||
DrawableLruCache mIconCache;
|
||||
BitmapLruCache mThumbnailCache;
|
||||
@@ -135,6 +135,7 @@ class TaskResourceLoader implements Runnable {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|start]");
|
||||
mContext = context;
|
||||
mCancelled = false;
|
||||
mSystemServicesProxy = new SystemServicesProxy(context);
|
||||
// Notify the load thread to start loading
|
||||
synchronized(mLoadThread) {
|
||||
mLoadThread.notifyAll();
|
||||
@@ -146,6 +147,7 @@ class TaskResourceLoader implements Runnable {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|stop]");
|
||||
// Mark as cancelled for the thread to pick up
|
||||
mCancelled = true;
|
||||
mSystemServicesProxy = null;
|
||||
// If we are waiting for the load queue for more tasks, then we can just reset the
|
||||
// Context now, since nothing is using it
|
||||
if (mWaitingOnLoadQueue) {
|
||||
@@ -175,66 +177,60 @@ class TaskResourceLoader implements Runnable {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SystemServicesProxy ssp = mSystemServicesProxy;
|
||||
|
||||
// Load the next item from the queue
|
||||
Pair<Task, Boolean> nextTaskData = mLoadQueue.nextTask();
|
||||
final Task t = nextTaskData.first;
|
||||
final boolean forceLoadTask = nextTaskData.second;
|
||||
if (t != null) {
|
||||
try {
|
||||
Drawable loadIcon = mIconCache.get(t.key);
|
||||
Bitmap loadThumbnail = mThumbnailCache.get(t.key);
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [TaskResourceLoader|load]",
|
||||
t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
|
||||
" forceLoad: " + forceLoadTask);
|
||||
// Load the icon
|
||||
if (loadIcon == null || forceLoadTask) {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
ActivityInfo info = pm.getActivityInfo(t.key.baseIntent.getComponent(),
|
||||
PackageManager.GET_META_DATA);
|
||||
Drawable icon = info.loadIcon(pm);
|
||||
if (!mCancelled) {
|
||||
if (icon != null) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [TaskResourceLoader|loadIcon]",
|
||||
icon);
|
||||
loadIcon = icon;
|
||||
mIconCache.put(t.key, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load the thumbnail
|
||||
if (loadThumbnail == null || forceLoadTask) {
|
||||
ActivityManager am = (ActivityManager)
|
||||
mContext.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
Bitmap thumbnail = am.getTaskTopThumbnail(t.key.id);
|
||||
if (!mCancelled) {
|
||||
if (thumbnail != null) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [TaskResourceLoader|loadThumbnail]",
|
||||
thumbnail);
|
||||
loadThumbnail = thumbnail;
|
||||
mThumbnailCache.put(t.key, thumbnail);
|
||||
} else {
|
||||
Console.logError(mContext,
|
||||
"Failed to load task top thumbnail for: " +
|
||||
t.key.baseIntent.getComponent().getPackageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Drawable loadIcon = mIconCache.get(t.key);
|
||||
Bitmap loadThumbnail = mThumbnailCache.get(t.key);
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [TaskResourceLoader|load]",
|
||||
t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
|
||||
" forceLoad: " + forceLoadTask);
|
||||
// Load the icon
|
||||
if (loadIcon == null || forceLoadTask) {
|
||||
ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent());
|
||||
Drawable icon = ssp.getActivityIcon(info);
|
||||
if (!mCancelled) {
|
||||
// Notify that the task data has changed
|
||||
final Drawable newIcon = loadIcon;
|
||||
final Bitmap newThumbnail = loadThumbnail;
|
||||
mMainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
|
||||
}
|
||||
});
|
||||
if (icon != null) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [TaskResourceLoader|loadIcon]",
|
||||
icon);
|
||||
loadIcon = icon;
|
||||
mIconCache.put(t.key, icon);
|
||||
}
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException ne) {
|
||||
ne.printStackTrace();
|
||||
}
|
||||
// Load the thumbnail
|
||||
if (loadThumbnail == null || forceLoadTask) {
|
||||
Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
|
||||
if (!mCancelled) {
|
||||
if (thumbnail != null) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [TaskResourceLoader|loadThumbnail]",
|
||||
thumbnail);
|
||||
loadThumbnail = thumbnail;
|
||||
mThumbnailCache.put(t.key, thumbnail);
|
||||
} else {
|
||||
Console.logError(mContext,
|
||||
"Failed to load task top thumbnail for: " +
|
||||
t.key.baseIntent.getComponent().getPackageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!mCancelled) {
|
||||
// Notify that the task data has changed
|
||||
final Drawable newIcon = loadIcon;
|
||||
final Bitmap newThumbnail = loadThumbnail;
|
||||
mMainThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,6 +292,7 @@ class BitmapLruCache extends LruCache<Task.TaskKey, Bitmap> {
|
||||
public class RecentsTaskLoader {
|
||||
static RecentsTaskLoader sInstance;
|
||||
|
||||
SystemServicesProxy mSystemServicesProxy;
|
||||
DrawableLruCache mIconCache;
|
||||
BitmapLruCache mThumbnailCache;
|
||||
TaskResourceLoadQueue mLoadQueue;
|
||||
@@ -324,7 +321,8 @@ public class RecentsTaskLoader {
|
||||
"[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
|
||||
" iconCache: " + iconCacheSize);
|
||||
|
||||
// Initialize the cache and loaders
|
||||
// Initialize the proxy, cache and loaders
|
||||
mSystemServicesProxy = new SystemServicesProxy(context);
|
||||
mLoadQueue = new TaskResourceLoadQueue();
|
||||
mIconCache = new DrawableLruCache(iconCacheSize);
|
||||
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
|
||||
@@ -358,6 +356,11 @@ public class RecentsTaskLoader {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/** Returns the system services proxy */
|
||||
public SystemServicesProxy getSystemServicesProxy() {
|
||||
return mSystemServicesProxy;
|
||||
}
|
||||
|
||||
/** Reload the set of recent tasks */
|
||||
SpaceNode reload(Context context, int preloadCount) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
|
||||
@@ -367,141 +370,129 @@ public class RecentsTaskLoader {
|
||||
SpaceNode root = new SpaceNode(context);
|
||||
root.setStack(stack);
|
||||
|
||||
try {
|
||||
long t1 = System.currentTimeMillis();
|
||||
long t1 = System.currentTimeMillis();
|
||||
|
||||
PackageManager pm = context.getPackageManager();
|
||||
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
// Get the recent tasks
|
||||
SystemServicesProxy ssp = mSystemServicesProxy;
|
||||
List<ActivityManager.RecentTaskInfo> tasks =
|
||||
ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
|
||||
Collections.reverse(tasks);
|
||||
Console.log(Constants.DebugFlags.App.TimeSystemCalls,
|
||||
"[RecentsTaskLoader|getRecentTasks]",
|
||||
"" + (System.currentTimeMillis() - t1) + "ms");
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
"[RecentsTaskLoader|tasks]", "" + tasks.size());
|
||||
|
||||
// Get the recent tasks
|
||||
List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(25,
|
||||
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
|
||||
ActivityManager.RECENT_INCLUDE_PROFILES, UserHandle.CURRENT.getIdentifier());
|
||||
Collections.reverse(tasks);
|
||||
Console.log(Constants.DebugFlags.App.TimeSystemCalls,
|
||||
"[RecentsTaskLoader|getRecentTasks]",
|
||||
"" + (System.currentTimeMillis() - t1) + "ms");
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
"[RecentsTaskLoader|tasks]", "" + tasks.size());
|
||||
// Remove home/recents tasks
|
||||
Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ActivityManager.RecentTaskInfo t = iter.next();
|
||||
|
||||
// Remove home/recents tasks
|
||||
Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
|
||||
while (iter.hasNext()) {
|
||||
ActivityManager.RecentTaskInfo t = iter.next();
|
||||
|
||||
// Skip tasks in the home stack
|
||||
if (am.isInHomeStack(t.persistentId)) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
// Skip tasks from this Recents package
|
||||
if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
// Skip tasks in the home stack
|
||||
if (ssp.isInHomeStack(t.persistentId)) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
// Skip tasks from this Recents package
|
||||
if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Add each task to the task stack
|
||||
t1 = System.currentTimeMillis();
|
||||
int taskCount = tasks.size();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
ActivityManager.RecentTaskInfo t = tasks.get(i);
|
||||
ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(),
|
||||
PackageManager.GET_META_DATA);
|
||||
String title = info.loadLabel(pm).toString();
|
||||
boolean isForemostTask = (i == (taskCount - 1));
|
||||
// Add each task to the task stack
|
||||
t1 = System.currentTimeMillis();
|
||||
int taskCount = tasks.size();
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
ActivityManager.RecentTaskInfo t = tasks.get(i);
|
||||
ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent());
|
||||
String title = ssp.getActivityLabel(info);
|
||||
boolean isForemostTask = (i == (taskCount - 1));
|
||||
|
||||
// Preload the specified number of apps
|
||||
if (i >= (taskCount - preloadCount)) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
"[RecentsTaskLoader|preloadTask]",
|
||||
"i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
|
||||
// Preload the specified number of apps
|
||||
if (i >= (taskCount - preloadCount)) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
"[RecentsTaskLoader|preloadTask]",
|
||||
"i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
|
||||
|
||||
String label = (t.activityLabel == null ? title : t.activityLabel.toString());
|
||||
BitmapDrawable bd = null;
|
||||
if (t.activityIcon != null) {
|
||||
bd = new BitmapDrawable(res, t.activityIcon);
|
||||
}
|
||||
Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, label, bd);
|
||||
String label = (t.activityLabel == null ? title : t.activityLabel.toString());
|
||||
BitmapDrawable bd = null;
|
||||
if (t.activityIcon != null) {
|
||||
bd = new BitmapDrawable(res, t.activityIcon);
|
||||
}
|
||||
Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, label, bd);
|
||||
|
||||
// Load the icon (if possible and not the foremost task, from the cache)
|
||||
if (task.icon != null) {
|
||||
mIconCache.put(task.key, task.icon);
|
||||
} else {
|
||||
if (!isForemostTask) {
|
||||
task.icon = mIconCache.get(task.key);
|
||||
if (task.icon != null) {
|
||||
// Even though we get things from the cache, we should update them
|
||||
// if they've changed in the bg
|
||||
tasksToForceLoad.add(task);
|
||||
}
|
||||
}
|
||||
if (task.icon == null) {
|
||||
task.icon = info.loadIcon(pm);
|
||||
if (task.icon != null) {
|
||||
mIconCache.put(task.key, task.icon);
|
||||
} else {
|
||||
task.icon = mDefaultIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the thumbnail (if possible and not the foremost task, from the cache)
|
||||
// Load the icon (if possible and not the foremost task, from the cache)
|
||||
if (task.icon != null) {
|
||||
mIconCache.put(task.key, task.icon);
|
||||
} else {
|
||||
if (!isForemostTask) {
|
||||
task.thumbnail = mThumbnailCache.get(task.key);
|
||||
if (task.thumbnail != null) {
|
||||
// Even though we get things from the cache, we should update them if
|
||||
// they've changed in the bg
|
||||
task.icon = mIconCache.get(task.key);
|
||||
if (task.icon != null) {
|
||||
// Even though we get things from the cache, we should update them
|
||||
// if they've changed in the bg
|
||||
tasksToForceLoad.add(task);
|
||||
}
|
||||
}
|
||||
if (task.thumbnail == null) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
"[RecentsTaskLoader|loadingTaskThumbnail]");
|
||||
task.thumbnail = am.getTaskTopThumbnail(t.id);
|
||||
if (task.thumbnail != null) {
|
||||
mThumbnailCache.put(task.key, task.thumbnail);
|
||||
if (task.icon == null) {
|
||||
task.icon = ssp.getActivityIcon(info);
|
||||
if (task.icon != null) {
|
||||
mIconCache.put(task.key, task.icon);
|
||||
} else {
|
||||
task.thumbnail = mDefaultThumbnail;
|
||||
task.icon = mDefaultIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create as many tasks a we want to multiply by
|
||||
for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
|
||||
stack.addTask(task);
|
||||
}
|
||||
} else {
|
||||
// Create as many tasks a we want to multiply by
|
||||
for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
|
||||
stack.addTask(new Task(t.persistentId, (t.id > -1), t.baseIntent, title,
|
||||
null, null));
|
||||
// Load the thumbnail (if possible and not the foremost task, from the cache)
|
||||
if (!isForemostTask) {
|
||||
task.thumbnail = mThumbnailCache.get(task.key);
|
||||
if (task.thumbnail != null) {
|
||||
// Even though we get things from the cache, we should update them if
|
||||
// they've changed in the bg
|
||||
tasksToForceLoad.add(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.log(Constants.DebugFlags.App.TimeSystemCalls,
|
||||
"[RecentsTaskLoader|getAllTaskTopThumbnail]",
|
||||
"" + (System.currentTimeMillis() - t1) + "ms");
|
||||
|
||||
/*
|
||||
// Get all the stacks
|
||||
t1 = System.currentTimeMillis();
|
||||
List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
|
||||
Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
|
||||
for (ActivityManager.StackInfo s : stackInfos) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader, " [RecentsTaskLoader|stack]", s.toString());
|
||||
if (stacks.containsKey(s.stackId)) {
|
||||
stacks.get(s.stackId).setRect(s.bounds);
|
||||
if (task.thumbnail == null) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
"[RecentsTaskLoader|loadingTaskThumbnail]");
|
||||
task.thumbnail = ssp.getTaskThumbnail(task.key.id);
|
||||
if (task.thumbnail != null) {
|
||||
mThumbnailCache.put(task.key, task.thumbnail);
|
||||
} else {
|
||||
task.thumbnail = mDefaultThumbnail;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the task to the stack
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
|
||||
stack.addTask(task);
|
||||
} else {
|
||||
// Add the task to the stack
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader,
|
||||
" [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
|
||||
stack.addTask(new Task(t.persistentId, (t.id > -1), t.baseIntent, title,
|
||||
null, null));
|
||||
}
|
||||
*/
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Console.log(Constants.DebugFlags.App.TimeSystemCalls,
|
||||
"[RecentsTaskLoader|getAllTaskTopThumbnail]",
|
||||
"" + (System.currentTimeMillis() - t1) + "ms");
|
||||
|
||||
/*
|
||||
// Get all the stacks
|
||||
t1 = System.currentTimeMillis();
|
||||
List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
|
||||
Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
|
||||
for (ActivityManager.StackInfo s : stackInfos) {
|
||||
Console.log(Constants.DebugFlags.App.TaskDataLoader, " [RecentsTaskLoader|stack]", s.toString());
|
||||
if (stacks.containsKey(s.stackId)) {
|
||||
stacks.get(s.stackId).setRect(s.bounds);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Start the task loader
|
||||
mLoader.start(context);
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.recents;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Acts as a shim around the real system services that we need to access data from, and provides
|
||||
* a point of injection when testing UI.
|
||||
*/
|
||||
public class SystemServicesProxy {
|
||||
ActivityManager mAm;
|
||||
PackageManager mPm;
|
||||
String mPackage;
|
||||
|
||||
Bitmap mDummyIcon;
|
||||
|
||||
/** Private constructor */
|
||||
public SystemServicesProxy(Context context) {
|
||||
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
mPm = context.getPackageManager();
|
||||
mPackage = context.getPackageName();
|
||||
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
|
||||
// Create a dummy icon
|
||||
mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
|
||||
Canvas c = new Canvas(mDummyIcon);
|
||||
c.drawColor(0xFFFF0000);
|
||||
c.setBitmap(null);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a list of the recents tasks */
|
||||
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
if (mAm == null) return null;
|
||||
|
||||
// If we are mocking, then create some recent tasks
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
|
||||
ArrayList<ActivityManager.RecentTaskInfo> tasks =
|
||||
new ArrayList<ActivityManager.RecentTaskInfo>();
|
||||
int count = Math.min(numTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
|
||||
for (int i = 0; i < count; i++) {
|
||||
// Create a dummy component name
|
||||
int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
|
||||
ComponentName cn = new ComponentName("com.android.test" + packageIndex,
|
||||
"com.android.test" + i + ".Activity");
|
||||
// Create the recent task info
|
||||
ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
|
||||
rti.id = rti.persistentId = i;
|
||||
rti.baseIntent = new Intent();
|
||||
rti.baseIntent.setComponent(cn);
|
||||
rti.description = rti.activityLabel = "Recent Task";
|
||||
rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
|
||||
tasks.add(rti);
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
return mAm.getRecentTasksForUser(numTasks,
|
||||
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
|
||||
ActivityManager.RECENT_INCLUDE_PROFILES, userId);
|
||||
}
|
||||
|
||||
/** Returns a list of the running tasks */
|
||||
public List<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) {
|
||||
if (mAm == null) return null;
|
||||
return mAm.getRunningTasks(numTasks);
|
||||
}
|
||||
|
||||
/** Returns whether the specified task is in the home stack */
|
||||
public boolean isInHomeStack(int taskId) {
|
||||
if (mAm == null) return false;
|
||||
|
||||
// If we are mocking, then just return false
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mAm.isInHomeStack(taskId);
|
||||
}
|
||||
|
||||
/** Returns the top task thumbnail for the given task id */
|
||||
public Bitmap getTaskThumbnail(int taskId) {
|
||||
if (mAm == null) return null;
|
||||
|
||||
// If we are mocking, then just return a dummy thumbnail
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
|
||||
Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(thumbnail);
|
||||
c.drawColor(0xFF00ff00);
|
||||
c.setBitmap(null);
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
return mAm.getTaskTopThumbnail(taskId);
|
||||
}
|
||||
|
||||
/** Moves a task to the front with the specified activity options */
|
||||
public void moveTaskToFront(int taskId, ActivityOptions opts) {
|
||||
if (mAm == null) return;
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
|
||||
|
||||
if (opts != null) {
|
||||
mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME,
|
||||
opts.toBundle());
|
||||
} else {
|
||||
mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME);
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes the task and kills the process */
|
||||
public void removeTask(int taskId) {
|
||||
if (mAm == null) return;
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
|
||||
|
||||
mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
|
||||
}
|
||||
|
||||
/** Returns the activity info for a given component name */
|
||||
public ActivityInfo getActivityInfo(ComponentName cn) {
|
||||
if (mPm == null) return null;
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
|
||||
|
||||
try {
|
||||
return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the activity label */
|
||||
public String getActivityLabel(ActivityInfo info) {
|
||||
if (mPm == null) return null;
|
||||
|
||||
// If we are mocking, then return a mock label
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
|
||||
return "Recent Task";
|
||||
}
|
||||
|
||||
return info.loadLabel(mPm).toString();
|
||||
}
|
||||
|
||||
/** Returns the activity icon */
|
||||
public Drawable getActivityIcon(ActivityInfo info) {
|
||||
if (mPm == null) return null;
|
||||
|
||||
// If we are mocking, then return a mock label
|
||||
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
|
||||
return new ColorDrawable(0xFFff0000);
|
||||
}
|
||||
|
||||
return info.loadIcon(mPm);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package com.android.systemui.recents.model;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import com.android.systemui.recents.Constants;
|
||||
|
||||
|
||||
/**
|
||||
@@ -106,14 +105,7 @@ public class Task {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
// If we have multiple task entries for the same task, then we do the simple object
|
||||
// equality check
|
||||
if (Constants.Values.RecentsTaskLoader.TaskEntryMultiplier > 1) {
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
// Otherwise, check that the id and intent match (the other fields can be asynchronously
|
||||
// loaded and is unsuitable to testing the identity of this Task)
|
||||
// Check that the id matches
|
||||
Task t = (Task) o;
|
||||
return key.equals(t.key);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.systemui.recents.views;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
@@ -30,6 +29,7 @@ import android.widget.FrameLayout;
|
||||
import com.android.systemui.recents.Console;
|
||||
import com.android.systemui.recents.Constants;
|
||||
import com.android.systemui.recents.RecentsConfiguration;
|
||||
import com.android.systemui.recents.RecentsTaskLoader;
|
||||
import com.android.systemui.recents.model.SpaceNode;
|
||||
import com.android.systemui.recents.model.Task;
|
||||
import com.android.systemui.recents.model.TaskStack;
|
||||
@@ -246,14 +246,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
||||
|
||||
if (task.isActive) {
|
||||
// Bring an active task to the foreground
|
||||
ActivityManager am = (ActivityManager)
|
||||
stackView.getContext().getSystemService(Context.ACTIVITY_SERVICE);
|
||||
if (opts != null) {
|
||||
am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME,
|
||||
opts.toBundle());
|
||||
} else {
|
||||
am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME);
|
||||
}
|
||||
RecentsTaskLoader.getInstance().getSystemServicesProxy()
|
||||
.moveTaskToFront(task.key.id, opts);
|
||||
} else {
|
||||
// Launch the activity with the desired animation
|
||||
Intent i = new Intent(task.key.baseIntent);
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
@@ -40,6 +39,7 @@ import com.android.systemui.recents.Console;
|
||||
import com.android.systemui.recents.Constants;
|
||||
import com.android.systemui.recents.RecentsConfiguration;
|
||||
import com.android.systemui.recents.RecentsTaskLoader;
|
||||
import com.android.systemui.recents.SystemServicesProxy;
|
||||
import com.android.systemui.recents.Utilities;
|
||||
import com.android.systemui.recents.model.Task;
|
||||
import com.android.systemui.recents.model.TaskStack;
|
||||
@@ -234,7 +234,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
// When we are picking up a new view from the view pool, prepare it for any
|
||||
// following animation by putting it in a reasonable place
|
||||
if (mStackViewsAnimationDuration > 0 && i != 0) {
|
||||
int fromIndex = (transform.t < 0) ? (i - 1) : (i + 1);
|
||||
int fromIndex = (transform.t < 0) ? (visibleRange[0] - 1) :
|
||||
(visibleRange[1] + 1);
|
||||
tv.updateViewPropertiesToTaskTransform(null,
|
||||
getStackTransform(fromIndex, stackScroll), 0);
|
||||
}
|
||||
@@ -1268,12 +1269,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
loader.deleteTaskData(task);
|
||||
|
||||
// Remove the task from activity manager
|
||||
final ActivityManager am = (ActivityManager)
|
||||
activity.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
if (am != null) {
|
||||
am.removeTask(tv.getTask().key.id,
|
||||
ActivityManager.REMOVE_TASK_KILL_PROCESS);
|
||||
}
|
||||
RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(tv.getTask().key.id);
|
||||
|
||||
// If there are no remaining tasks, then either unfilter the current stack, or just close
|
||||
// the activity if there are no filtered stacks
|
||||
|
||||
Reference in New Issue
Block a user