Merge "Adding system service proxy to help test UI/performance."

This commit is contained in:
Winson Chung
2014-04-02 22:14:19 +00:00
committed by Android (Google) Code Review
8 changed files with 368 additions and 217 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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