summaryrefslogtreecommitdiff
path: root/services/java/com/android/server/pm/UserManagerService.java
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2012-10-17 21:16:52 -0700
committerAmith Yamasani <yamasani@google.com>2012-10-19 16:23:30 -0700
commitdb6a14cc85cede0769735fdac4da70766989a3ce (patch)
tree746e34df3a9ae15f9e1934033f8d907173fbd725 /services/java/com/android/server/pm/UserManagerService.java
parentba0372db366e63fa928ba83f3ad8c064c51ac8e0 (diff)
Fix crashes when quickly adding and removing users
Make USER_REMOVED an ordered broadcast and send it before the user's state is completely removed from the system. This gives services the opportunity to clean up their state, while still having access to the user's directory and UserInfo object (such as serial number). Tell SyncManager to skip over dying/partially created users. Improve UserManager tests, waiting for users to be removed fully. Bug: 7382252 Change-Id: I93cfb39c9efe6f15087bf83c569a2d154ef27168
Diffstat (limited to 'services/java/com/android/server/pm/UserManagerService.java')
-rw-r--r--services/java/com/android/server/pm/UserManagerService.java39
1 files changed, 29 insertions, 10 deletions
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 072dd331b23c..fb93d059a14b 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -19,9 +19,11 @@ package com.android.server.pm;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IStopUserCallback;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -736,21 +738,38 @@ public class UserManagerService extends IUserManager.Stub {
return res == ActivityManager.USER_OP_SUCCESS;
}
- void finishRemoveUser(int userHandle) {
+ void finishRemoveUser(final int userHandle) {
if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle);
- synchronized (mInstallLock) {
- synchronized (mPackagesLock) {
- removeUserStateLocked(userHandle);
- }
- }
- if (DBG) Slog.i(LOG_TAG, "Removed user " + userHandle + ", sending broadcast");
- // Let other services shutdown any activity
+ // Let other services shutdown any activity and clean up their state before completely
+ // wiping the user's system directory and removing from the user list
long ident = Binder.clearCallingIdentity();
try {
Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
- mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
- android.Manifest.permission.MANAGE_USERS);
+ mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
+ android.Manifest.permission.MANAGE_USERS,
+
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DBG) {
+ Slog.i(LOG_TAG,
+ "USER_REMOVED broadcast sent, cleaning up user data "
+ + userHandle);
+ }
+ new Thread() {
+ public void run() {
+ synchronized (mInstallLock) {
+ synchronized (mPackagesLock) {
+ removeUserStateLocked(userHandle);
+ }
+ }
+ }
+ }.start();
+ }
+ },
+
+ null, Activity.RESULT_OK, null, null);
} finally {
Binder.restoreCallingIdentity(ident);
}