diff options
4 files changed, 50 insertions, 17 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 40eb799f26b9..373a23fa7422 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -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); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index bd10c63edbda..9753331fdd41 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -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 { diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java index aa154a7c3850..871331b770e2 100644 --- a/services/core/java/com/android/server/am/TaskPersister.java +++ b/services/core/java/com/android/server/am/TaskPersister.java @@ -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)); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index de106a1d0d3c..6386a916d518 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -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; @@ -1010,7 +1016,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)); @@ -1587,6 +1594,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); @@ -1951,14 +1961,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); } |