am 623484d2: Merge "Ensuring that user-specific Recent tasks are removed. (Bug 18036610)" into lmp-mr1-dev

* commit '623484d231436ee209089adaa6b88b68f0ebf534':
  Ensuring that user-specific Recent tasks are removed. (Bug 18036610)
This commit is contained in:
Winson Chung
2014-10-24 18:30:38 +00:00
committed by Android Git Automerger
7 changed files with 58 additions and 46 deletions

View File

@@ -21,15 +21,16 @@ import android.util.LruCache;
import java.util.HashMap;
/**
* An LRU cache that support querying the keys as well as values. By using the Task's key, we can
* prevent holding onto a reference to the Task resource data, while keeping the cache data in
* memory where necessary.
* An LRU cache that internally support querying the keys as well as values. We use this to keep
* track of the task metadata to determine when to invalidate the cache when tasks have been
* updated. Generally, this cache will return the last known cache value for the requested task
* key.
*/
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<Integer, Task.TaskKey> mTaskKeys = new HashMap<Integer, Task.TaskKey>();
// The cache implementation
// The cache implementation, mapping task id -> value
LruCache<Integer, V> mCache;
public KeyStoreLruCache(int cacheSize) {

View File

@@ -19,6 +19,7 @@ package com.android.systemui.recents.model;
import android.content.ComponentName;
import android.content.Context;
import android.os.Looper;
import android.os.UserHandle;
import com.android.internal.content.PackageMonitor;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -26,16 +27,16 @@ import java.util.HashSet;
import java.util.List;
/**
* The package monitor listens for changes from PackageManager to update the contents of the Recents
* list.
* The package monitor listens for changes from PackageManager to update the contents of the
* Recents list.
*/
public class RecentsPackageMonitor extends PackageMonitor {
public interface PackageCallbacks {
public void onComponentRemoved(HashSet<ComponentName> cns);
public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName,
int userId);
}
PackageCallbacks mCb;
List<Task.TaskKey> mTasks;
SystemServicesProxy mSystemServicesProxy;
/** Registers the broadcast receivers with the specified callbacks. */
@@ -43,7 +44,9 @@ public class RecentsPackageMonitor extends PackageMonitor {
mSystemServicesProxy = new SystemServicesProxy(context);
mCb = cb;
try {
register(context, Looper.getMainLooper(), true);
// We register for events from all users, but will cross-reference them with
// packages for the current user and any profiles they have
register(context, Looper.getMainLooper(), UserHandle.ALL, true);
} catch (IllegalStateException e) {
e.printStackTrace();
}
@@ -59,29 +62,15 @@ public class RecentsPackageMonitor extends PackageMonitor {
}
mSystemServicesProxy = null;
mCb = null;
mTasks.clear();
}
/** Sets the list of tasks to match against package broadcast changes. */
void setTasks(List<Task.TaskKey> tasks) {
mTasks = tasks;
}
@Override
public void onPackageRemoved(String packageName, int uid) {
if (mCb == null) return;
// Identify all the tasks that should be removed as a result of the package being removed.
// Using a set to ensure that we callback once per unique component.
HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
for (Task.TaskKey t : mTasks) {
ComponentName cn = t.baseIntent.getComponent();
if (cn.getPackageName().equals(packageName)) {
componentsToRemove.add(cn);
}
}
// Notify our callbacks that the components no longer exist
mCb.onComponentRemoved(componentsToRemove);
// Notify callbacks that a package has changed
final int eventUserId = getChangingUserId();
mCb.onPackagesChanged(this, packageName, eventUserId);
}
@Override
@@ -94,25 +83,38 @@ public class RecentsPackageMonitor extends PackageMonitor {
public void onPackageModified(String packageName) {
if (mCb == null) return;
// Notify callbacks that a package has changed
final int eventUserId = getChangingUserId();
mCb.onPackagesChanged(this, packageName, eventUserId);
}
/**
* Computes the components that have been removed as a result of a change in the specified
* package.
*/
public HashSet<ComponentName> computeComponentsRemoved(List<Task.TaskKey> taskKeys,
String packageName, int userId) {
// Identify all the tasks that should be removed as a result of the package being removed.
// Using a set to ensure that we callback once per unique component.
HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
for (Task.TaskKey t : mTasks) {
HashSet<ComponentName> existingComponents = new HashSet<ComponentName>();
HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
for (Task.TaskKey t : taskKeys) {
// Skip if this doesn't apply to the current user
if (t.userId != userId) continue;
ComponentName cn = t.baseIntent.getComponent();
if (cn.getPackageName().equals(packageName)) {
if (componentsKnownToExist.contains(cn)) {
if (existingComponents.contains(cn)) {
// If we know that the component still exists in the package, then skip
continue;
}
if (mSystemServicesProxy.getActivityInfo(cn) != null) {
componentsKnownToExist.add(cn);
if (mSystemServicesProxy.getActivityInfo(cn, userId) != null) {
existingComponents.add(cn);
} else {
componentsToRemove.add(cn);
removedComponents.add(cn);
}
}
}
// Notify our callbacks that the components no longer exist
mCb.onComponentRemoved(componentsToRemove);
return removedComponents;
}
}

View File

@@ -420,10 +420,6 @@ public class RecentsTaskLoader {
// Start the task loader and add all the tasks we need to load
mLoader.start(context);
mLoadQueue.addTasks(tasksToLoad);
// Update the package monitor with the list of packages to listen for
mPackageMonitor.setTasks(taskKeys);
return root;
}

View File

@@ -129,7 +129,7 @@ public class Task {
TaskCallbacks mCb;
public Task() {
// Only used by RecentsService for task rect calculations.
// Do nothing
}
public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,

View File

@@ -255,6 +255,17 @@ public class TaskStack {
return mTaskList.getTasks().get(mTaskList.size() - 1);
}
/** Gets the task keys */
public ArrayList<Task.TaskKey> getTaskKeys() {
ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>();
ArrayList<Task> tasks = mTaskList.getTasks();
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
taskKeys.add(tasks.get(i).key);
}
return taskKeys;
}
/** Gets the tasks */
public ArrayList<Task> getTasks() {
return mTaskList.getTasks();

View File

@@ -18,7 +18,6 @@ package com.android.systemui.recents.views;
import android.app.ActivityOptions;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -42,7 +41,6 @@ import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.HashSet;
/**
* This view is the the top level layout that contains TaskStacks (which are laid out according
@@ -564,14 +562,14 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
public void onComponentRemoved(HashSet<ComponentName> cns) {
public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) {
// Propagate this event down to each task stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
stackView.onComponentRemoved(cns);
stackView.onPackagesChanged(monitor, packageName, userId);
}
}
}

View File

@@ -1081,12 +1081,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
public void onComponentRemoved(HashSet<ComponentName> cns) {
public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) {
// Compute which components need to be removed
HashSet<ComponentName> removedComponents = monitor.computeComponentsRemoved(
mStack.getTaskKeys(), packageName, userId);
// For other tasks, just remove them directly if they no longer exist
ArrayList<Task> tasks = mStack.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
final Task t = tasks.get(i);
if (cns.contains(t.key.baseIntent.getComponent())) {
if (removedComponents.contains(t.key.baseIntent.getComponent())) {
TaskView tv = getChildViewForTask(t);
if (tv != null) {
// For visible children, defer removing the task until after the animation