Delay cleaning user tasks until user is removed

Fixes #24301208 No recent apps shows when switching
between users.

Instead of cleaning up when stopping a user, we
should remove tasks when removing a user, since
recents tasks should be persisted across reboots.
Reboots are similar to stopping and starting users.

Change-Id: I9a250792077cca5f18ae1a10bc36f7b97e8ea867
This commit is contained in:
Amith Yamasani
2015-09-28 11:30:06 -07:00
parent dfc9ce5477
commit 515d40600e
4 changed files with 50 additions and 17 deletions

View File

@@ -55,4 +55,13 @@ public abstract class ActivityManagerInternal {
* @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
*/
public abstract ComponentName getHomeActivityForUser(int userId);
/**
* Called when a user has been deleted. This can happen during normal device usage
* or just at startup, when partially removed users are purged. Any state persisted by the
* ActivityManager should be purged now.
*
* @param userId The user being cleaned up.
*/
public abstract void onUserRemoved(int userId);
}

View File

@@ -11893,7 +11893,8 @@ public final class ActivityManagerService extends ActivityManagerNative
updateCurrentProfileIdsLocked();
mRecentTasks.clear();
mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
mRecentTasks.addAll(mTaskPersister.restoreTasksLocked(
getUserManagerLocked().getUserIds()));
mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
mTaskPersister.startPersisting();
@@ -20644,9 +20645,6 @@ public final class ActivityManagerService extends ActivityManagerNative
// Kill all the processes for the user.
forceStopUserLocked(userId, "finish user");
}
// Explicitly remove the old information in mRecentTasks.
mRecentTasks.removeTasksForUserLocked(userId);
}
for (int i=0; i<callbacks.size(); i++) {
@@ -20665,6 +20663,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
void onUserRemovedLocked(int userId) {
mRecentTasks.removeTasksForUserLocked(userId);
}
@Override
public UserInfo getCurrentUser() {
if ((checkCallingPermission(INTERACT_ACROSS_USERS)
@@ -20949,6 +20951,13 @@ public final class ActivityManagerService extends ActivityManagerNative
return homeActivity == null ? null : homeActivity.realActivity;
}
}
@Override
public void onUserRemoved(int userId) {
synchronized (ActivityManagerService.this) {
ActivityManagerService.this.onUserRemovedLocked(userId);
}
}
}
private final class SleepTokenImpl extends SleepToken {

View File

@@ -35,6 +35,7 @@ import android.util.SparseArray;
import android.util.Xml;
import android.os.Process;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
@@ -330,7 +331,7 @@ public class TaskPersister {
return null;
}
ArrayList<TaskRecord> restoreTasksLocked() {
ArrayList<TaskRecord> restoreTasksLocked(final int [] validUserIds) {
final ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>();
ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>();
@@ -362,15 +363,18 @@ public class TaskPersister {
if (DEBUG) Slog.d(TAG, "restoreTasksLocked: restored task=" +
task);
if (task != null) {
task.isPersistable = true;
// XXX Don't add to write queue... there is no reason to write
// out the stuff we just read, if we don't write it we will
// read the same thing again.
//mWriteQueue.add(new TaskWriteQueueItem(task));
tasks.add(task);
final int taskId = task.taskId;
recoveredTaskIds.add(taskId);
mStackSupervisor.setNextTaskId(taskId);
// Check if it's a valid user id. Don't add tasks for removed users.
if (ArrayUtils.contains(validUserIds, task.userId)) {
task.isPersistable = true;
tasks.add(task);
recoveredTaskIds.add(taskId);
}
} else {
Slog.e(TAG, "Unable to restore taskFile=" + taskFile + ": " +
fileToString(taskFile));

View File

@@ -20,6 +20,7 @@ import android.accounts.Account;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
import android.app.IStopUserCallback;
import android.app.admin.DevicePolicyManager;
@@ -64,7 +65,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.accounts.AccountManagerService;
import com.android.server.LocalServices;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -242,13 +243,15 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mPackagesLock) {
// Prune out any partially created/partially removed users.
ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
for (int i = 0; i < mUsers.size(); i++) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo ui = mUsers.valueAt(i);
if ((ui.partial || ui.guestToRemove) && i != 0) {
partials.add(ui);
}
}
for (int i = 0; i < partials.size(); i++) {
final int partialsSize = partials.size();
for (int i = 0; i < partialsSize; i++) {
UserInfo ui = partials.get(i);
Slog.w(LOG_TAG, "Removing partially created user " + ui.id
+ " (name=" + ui.name + ")");
@@ -272,7 +275,8 @@ public class UserManagerService extends IUserManager.Stub {
public UserInfo getPrimaryUser() {
checkManageUsersPermission("query users");
synchronized (mPackagesLock) {
for (int i = 0; i < mUsers.size(); i++) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo ui = mUsers.valueAt(i);
if (ui.isPrimary()) {
return ui;
@@ -287,7 +291,8 @@ public class UserManagerService extends IUserManager.Stub {
checkManageUsersPermission("query users");
synchronized (mPackagesLock) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo ui = mUsers.valueAt(i);
if (ui.partial) {
continue;
@@ -323,7 +328,8 @@ public class UserManagerService extends IUserManager.Stub {
// Probably a dying user
return users;
}
for (int i = 0; i < mUsers.size(); i++) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo profile = mUsers.valueAt(i);
if (!isProfileOf(user, profile)) {
continue;
@@ -978,7 +984,8 @@ public class UserManagerService extends IUserManager.Stub {
serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
writeRestrictionsLocked(serializer, mGuestRestrictions);
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
for (int i = 0; i < mUsers.size(); i++) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
UserInfo user = mUsers.valueAt(i);
serializer.startTag(null, TAG_USER);
serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
@@ -1555,6 +1562,9 @@ public class UserManagerService extends IUserManager.Stub {
}
new Thread() {
public void run() {
// Clean up any ActivityManager state
LocalServices.getService(ActivityManagerInternal.class)
.onUserRemoved(userHandle);
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
removeUserStateLocked(userHandle);
@@ -1919,14 +1929,15 @@ public class UserManagerService extends IUserManager.Stub {
*/
private void updateUserIdsLocked() {
int num = 0;
for (int i = 0; i < mUsers.size(); i++) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
if (!mUsers.valueAt(i).partial) {
num++;
}
}
final int[] newUsers = new int[num];
int n = 0;
for (int i = 0; i < mUsers.size(); i++) {
for (int i = 0; i < userSize; i++) {
if (!mUsers.valueAt(i).partial) {
newUsers[n++] = mUsers.keyAt(i);
}