User Manager service to manage users and query user details
Moved a bunch of methods from PackageManager to UserManager.
Fix launching of activities from recents to correct user.
Guest creation APIs
Change-Id: I0733405e6eb2829675665e225c759d6baa2b708f
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 96cf3d3..e8350c1 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -55,6 +55,7 @@
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.UserManagerService;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.usb.UsbService;
@@ -192,6 +193,11 @@
}
ActivityManagerService.setSystemProcess();
+
+ Slog.i(TAG, "User Service");
+ ServiceManager.addService(Context.USER_SERVICE,
+ UserManagerService.getInstance(context));
+
mContentResolver = context.getContentResolver();
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index df6c51e..533c2cd 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1835,7 +1835,7 @@
pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
try {
- List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
+ List<UserInfo> users = mAm.getUserManager().getUsers();
for (UserInfo user : users) {
if (mServiceMap.getAllServices(user.id).size() > 0) {
boolean printed = false;
@@ -1913,8 +1913,8 @@
needSep = printed;
}
}
- } catch (RemoteException re) {
-
+ } catch (Exception e) {
+ Log.w(TAG, "Exception in dumpServicesLocked: " + e);
}
if (mPendingServices.size() > 0) {
@@ -2028,16 +2028,13 @@
int opti, boolean dumpAll) {
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
+ List<UserInfo> users = mAm.getUserManager().getUsers();
if ("all".equals(name)) {
synchronized (this) {
- try {
- List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
- for (UserInfo user : users) {
- for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
- services.add(r1);
- }
+ for (UserInfo user : users) {
+ for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
+ services.add(r1);
}
- } catch (RemoteException re) {
}
}
} else {
@@ -2055,24 +2052,20 @@
}
synchronized (this) {
- try {
- List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
- for (UserInfo user : users) {
- for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
- if (componentName != null) {
- if (r1.name.equals(componentName)) {
- services.add(r1);
- }
- } else if (name != null) {
- if (r1.name.flattenToString().contains(name)) {
- services.add(r1);
- }
- } else if (System.identityHashCode(r1) == objectId) {
+ for (UserInfo user : users) {
+ for (ServiceRecord r1 : mServiceMap.getAllServices(user.id)) {
+ if (componentName != null) {
+ if (r1.name.equals(componentName)) {
services.add(r1);
}
+ } else if (name != null) {
+ if (r1.name.flattenToString().contains(name)) {
+ services.add(r1);
+ }
+ } else if (System.identityHashCode(r1) == objectId) {
+ services.add(r1);
}
}
- } catch (RemoteException re) {
}
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5bed015..d3ec9f7 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -27,6 +27,7 @@
import com.android.server.SystemServer;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.pm.UserManagerService;
import com.android.server.wm.WindowManagerService;
import dalvik.system.Zygote;
@@ -76,12 +77,12 @@
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.UserInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@@ -111,6 +112,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserId;
+import android.os.UserManager;
import android.provider.Settings;
import android.text.format.Time;
import android.util.EventLog;
@@ -778,6 +780,10 @@
static ActivityManagerService mSelf;
static ActivityThread mSystemThread;
+ private int mCurrentUserId;
+ private SparseIntArray mLoggedInUsers = new SparseIntArray(5);
+ private UserManager mUserManager;
+
private final class AppDeathRecipient implements IBinder.DeathRecipient {
final ProcessRecord mApp;
final int mPid;
@@ -4197,19 +4203,14 @@
// Tell anyone interested that we are done booting!
SystemProperties.set("sys.boot_completed", "1");
SystemProperties.set("dev.bootcomplete", "1");
- try {
- List<UserInfo> users = AppGlobals.getPackageManager().getUsers();
- for (UserInfo user : users) {
- broadcastIntentLocked(null, null,
- new Intent(Intent.ACTION_BOOT_COMPLETED, null),
- null, null, 0, null, null,
- android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
- false, false, MY_PID, Process.SYSTEM_UID, user.id);
- }
- } catch (RemoteException re) {
- // Won't happen, in same process
+ List<UserInfo> users = getUserManager().getUsers();
+ for (UserInfo user : users) {
+ broadcastIntentLocked(null, null,
+ new Intent(Intent.ACTION_BOOT_COMPLETED, null),
+ null, null, 0, null, null,
+ android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
+ false, false, MY_PID, Process.SYSTEM_UID, user.id);
}
-
}
}
}
@@ -13358,9 +13359,6 @@
// Multi-user methods
- private int mCurrentUserId;
- private SparseIntArray mLoggedInUsers = new SparseIntArray(5);
-
public boolean switchUser(int userId) {
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != Process.myUid()) {
@@ -13403,7 +13401,7 @@
Slog.e(TAG, "Trying to get user from unauthorized app");
return null;
}
- return AppGlobals.getPackageManager().getUser(mCurrentUserId);
+ return getUserManager().getUserInfo(mCurrentUserId);
}
private void onUserRemoved(Intent intent) {
@@ -13431,14 +13429,15 @@
}
private boolean userExists(int userId) {
- try {
- UserInfo user = AppGlobals.getPackageManager().getUser(userId);
- return user != null;
- } catch (RemoteException re) {
- // Won't happen, in same process
- }
+ UserInfo user = getUserManager().getUserInfo(userId);
+ return user != null;
+ }
- return false;
+ UserManager getUserManager() {
+ if (mUserManager == null) {
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ }
+ return mUserManager;
}
private void checkValidCaller(int uid, int userId) {
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 7e5f8cf..46c24b0 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -113,6 +113,7 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.UserId;
+import android.os.UserManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.format.Formatter;
@@ -1707,7 +1708,8 @@
}
private void updateRulesForAppLocked(int appId) {
- for (UserInfo user : mContext.getPackageManager().getUsers()) {
+ UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ for (UserInfo user : um.getUsers()) {
final int uid = UserId.getUid(user.id, appId);
updateRulesForUidLocked(uid);
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 180081b..f257203 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -68,6 +68,7 @@
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
+import android.content.pm.UserInfo;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageStats;
import android.content.pm.ParceledListSlice;
@@ -77,7 +78,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
-import android.content.pm.UserInfo;
import android.content.pm.ManifestDigest;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
@@ -101,6 +101,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserId;
+import android.os.UserManager;
import android.provider.Settings.Secure;
import android.security.SystemKeyStore;
import android.util.DisplayMetrics;
@@ -420,7 +421,7 @@
// Delay time in millisecs
static final int BROADCAST_DELAY = 10 * 1000;
- static UserManager sUserManager;
+ static UserManagerService sUserManager;
// Stores a list of users whose package restrictions file needs to be updated
private HashSet<Integer> mDirtyUsers = new HashSet<Integer>();
@@ -899,7 +900,7 @@
mOnlyCore = onlyCore;
mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
mMetrics = new DisplayMetrics();
- mSettings = new Settings();
+ mSettings = new Settings(context);
mSettings.addSharedUserLPw("android.uid.system",
Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
@@ -942,11 +943,12 @@
mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
- sUserManager = new UserManager(mInstaller, mUserAppDataDir);
+ sUserManager = UserManagerService.getInstance(context);
+ sUserManager.setInstaller(this, mInstaller);
readPermissions();
- mRestoredSettings = mSettings.readLPw(getUsers());
+ mRestoredSettings = mSettings.readLPw(sUserManager.getUsers());
long startTime = SystemClock.uptimeMillis();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
@@ -9459,48 +9461,16 @@
PackageHelper.APP_INSTALL_AUTO);
}
- public UserInfo createUser(String name, int flags) {
- // TODO(kroot): Add a real permission for creating users
- enforceSystemOrRoot("Only the system can create users");
-
- UserInfo userInfo = sUserManager.createUser(name, flags);
- if (userInfo != null) {
- Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
- addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
- mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
- }
- return userInfo;
- }
-
- public boolean removeUser(int userId) {
- // TODO(kroot): Add a real permission for removing users
- enforceSystemOrRoot("Only the system can remove users");
-
- if (userId == 0 || !sUserManager.exists(userId)) {
- return false;
- }
-
- cleanUpUser(userId);
-
- if (sUserManager.removeUser(userId)) {
- // Let other services shutdown any activity
- Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
- addedIntent.putExtra(Intent.EXTRA_USERID, userId);
- mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
- }
- sUserManager.removePackageFolders(userId);
- return true;
- }
-
- private void cleanUpUser(int userId) {
+ /** Called by UserManagerService */
+ void cleanUpUser(int userHandle) {
// Disable all the packages for the user first
synchronized (mPackages) {
Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
for (Entry<String, PackageSetting> entry : entries) {
- entry.getValue().removeUser(userId);
+ entry.getValue().removeUser(userHandle);
}
- if (mDirtyUsers.remove(userId));
- mSettings.removeUserLPr(userId);
+ if (mDirtyUsers.remove(userHandle));
+ mSettings.removeUserLPr(userHandle);
}
}
@@ -9516,30 +9486,6 @@
}
@Override
- public List<UserInfo> getUsers() {
- enforceSystemOrRoot("Only the system can query users");
- return sUserManager.getUsers();
- }
-
- @Override
- public UserInfo getUser(int userId) {
- enforceSystemOrRoot("Only the system can query user");
- return sUserManager.getUser(userId);
- }
-
- @Override
- public void setUserName(int userId, String name) {
- enforceSystemOrRoot("Only the system can rename users");
- sUserManager.setUserName(userId, name);
- }
-
- @Override
- public ParcelFileDescriptor setUserIcon(int userId) {
- enforceSystemOrRoot("Only the system can update users");
- return sUserManager.setUserIcon(userId);
- }
-
- @Override
public void setPermissionEnforced(String permission, boolean enforced) {
mContext.enforceCallingOrSelfPermission(GRANT_REVOKE_PERMISSIONS, null);
if (READ_EXTERNAL_STORAGE.equals(permission)) {
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index def1696..add91d3 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -34,6 +34,7 @@
import android.app.AppGlobals;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
@@ -79,6 +80,7 @@
private static final String TAG = "PackageSettings";
private static final boolean DEBUG_STOPPED = false;
+ private static final boolean DEBUG_MU = false;
private static final String TAG_READ_EXTERNAL_STORAGE = "read-external-storage";
private static final String ATTR_ENFORCEMENT = "enforcement";
@@ -173,12 +175,15 @@
*/
private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>();
+ private final Context mContext;
+
private final File mSystemDir;
- Settings() {
- this(Environment.getDataDirectory());
+ Settings(Context context) {
+ this(context, Environment.getDataDirectory());
}
- Settings(File dataDir) {
+ Settings(Context context, File dataDir) {
+ mContext = context;
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
FileUtils.setPermissions(mSystemDir.toString(),
@@ -739,6 +744,9 @@
}
void readPackageRestrictionsLPr(int userId) {
+ if (DEBUG_MU) {
+ Log.i(TAG, "Reading package restrictions for user=" + userId);
+ }
FileInputStream str = null;
File userPackagesStateFile = getUserPackagesStateFile(userId);
File backupFile = getUserPackagesStateBackupFile(userId);
@@ -891,6 +899,9 @@
}
void writePackageRestrictionsLPr(int userId) {
+ if (DEBUG_MU) {
+ Log.i(TAG, "Writing package restrictions for user=" + userId);
+ }
// Keep the old stopped packages around until we know the new ones have
// been successfully written.
File userPackagesStateFile = getUserPackagesStateFile(userId);
@@ -935,6 +946,7 @@
boolean stopped = pkg.getStopped(userId);
boolean notLaunched = pkg.getNotLaunched(userId);
int enabled = pkg.getEnabled(userId);
+ if (DEBUG_MU) Log.i(TAG, " pkg=" + pkg.name + ", state=" + enabled);
HashSet<String> enabledComponents = pkg.getEnabledComponents(userId);
HashSet<String> disabledComponents = pkg.getDisabledComponents(userId);
@@ -1584,7 +1596,24 @@
mReadMessages.append("Error reading: " + e.toString());
PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
Log.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
+ }
+ if (mBackupStoppedPackagesFilename.exists()
+ || mStoppedPackagesFilename.exists()) {
+ // Read old file
+ readStoppedLPw();
+ mBackupStoppedPackagesFilename.delete();
+ mStoppedPackagesFilename.delete();
+ // Migrate to new file format
+ writePackageRestrictionsLPr(0);
+ } else {
+ if (users == null) {
+ readPackageRestrictionsLPr(0);
+ } else {
+ for (UserInfo user : users) {
+ readPackageRestrictionsLPr(user.id);
+ }
+ }
}
final int N = mPendingPackages.size();
@@ -1628,23 +1657,6 @@
}
}
- if (mBackupStoppedPackagesFilename.exists()
- || mStoppedPackagesFilename.exists()) {
- // Read old file
- readStoppedLPw();
- mBackupStoppedPackagesFilename.delete();
- mStoppedPackagesFilename.delete();
- // Migrate to new file format
- writePackageRestrictionsLPr(0);
- } else {
- if (users == null) {
- readPackageRestrictionsLPr(0);
- } else {
- for (UserInfo user : users) {
- readPackageRestrictionsLPr(user.id);
- }
- }
- }
mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
+ mSharedUsers.size() + " shared uids\n");
@@ -2378,9 +2390,7 @@
private List<UserInfo> getAllUsers() {
long id = Binder.clearCallingIdentity();
try {
- return AppGlobals.getPackageManager().getUsers();
- } catch (RemoteException re) {
- // Local to system process, shouldn't happen
+ return UserManagerService.getInstance(mContext).getUsers();
} catch (NullPointerException npe) {
// packagemanager not yet initialized
} finally {
diff --git a/services/java/com/android/server/pm/UserManager.java b/services/java/com/android/server/pm/UserManagerService.java
similarity index 78%
rename from services/java/com/android/server/pm/UserManager.java
rename to services/java/com/android/server/pm/UserManagerService.java
index 738ab08..b55dd24 100644
--- a/services/java/com/android/server/pm/UserManager.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -22,12 +22,17 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import android.content.Context;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
+import android.os.IUserManager;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.SystemClock;
import android.os.UserId;
import android.util.Log;
@@ -48,9 +53,9 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
-public class UserManager {
+public class UserManagerService extends IUserManager.Stub {
- private static final String TAG = "UserManager";
+ private static final String TAG = "UserManagerService";
private static final String TAG_NAME = "name";
@@ -75,14 +80,25 @@
private final File mUsersDir;
private final File mUserListFile;
private int[] mUserIds;
+ private boolean mGuestEnabled;
private Installer mInstaller;
private File mBaseUserPath;
+ private Context mContext;
+ private static UserManagerService sInstance;
+ private PackageManagerService mPm;
+
+ public synchronized static UserManagerService getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new UserManagerService(context);
+ }
+ return sInstance;
+ }
/**
* Available for testing purposes.
*/
- UserManager(File dataDir, File baseUserPath) {
+ UserManagerService(File dataDir, File baseUserPath) {
mUsersDir = new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
// Make zeroth user directory, for services to migrate their files to that location
@@ -97,12 +113,19 @@
readUserList();
}
- public UserManager(Installer installer, File baseUserPath) {
- this(Environment.getDataDirectory(), baseUserPath);
- mInstaller = installer;
+ public UserManagerService(Context context) {
+ this(Environment.getDataDirectory(), new File(Environment.getDataDirectory(), "user"));
+ mContext = context;
}
+ void setInstaller(PackageManagerService pm, Installer installer) {
+ mInstaller = installer;
+ mPm = pm;
+ }
+
+ @Override
public List<UserInfo> getUsers() {
+ enforceSystemOrRoot("Only the system can query users");
synchronized (mUsers) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) {
@@ -112,7 +135,9 @@
}
}
- public UserInfo getUser(int userId) {
+ @Override
+ public UserInfo getUserInfo(int userId) {
+ enforceSystemOrRoot("Only the system can query user");
synchronized (mUsers) {
UserInfo info = mUsers.get(userId);
return info;
@@ -125,7 +150,9 @@
}
}
+ @Override
public void setUserName(int userId, String name) {
+ enforceSystemOrRoot("Only the system can rename users");
synchronized (mUsers) {
UserInfo info = mUsers.get(userId);
if (name != null && !name.equals(info.name)) {
@@ -135,7 +162,9 @@
}
}
+ @Override
public ParcelFileDescriptor setUserIcon(int userId) {
+ enforceSystemOrRoot("Only the system can update users");
synchronized (mUsers) {
UserInfo info = mUsers.get(userId);
if (info == null) return null;
@@ -147,6 +176,57 @@
}
}
+ @Override
+ public void setGuestEnabled(boolean enable) {
+ enforceSystemOrRoot("Only the system can enable guest users");
+ synchronized (mUsers) {
+ if (mGuestEnabled != enable) {
+ mGuestEnabled = enable;
+ // Erase any guest user that currently exists
+ for (int i = 0; i < mUsers.size(); i++) {
+ UserInfo user = mUsers.valueAt(i);
+ if (user.isGuest()) {
+ if (!enable) {
+ removeUser(user.id);
+ }
+ return;
+ }
+ }
+ // No guest was found
+ if (enable) {
+ createUser("Guest", UserInfo.FLAG_GUEST);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean isGuestEnabled() {
+ synchronized (mUsers) {
+ return mGuestEnabled;
+ }
+ }
+
+ @Override
+ public void wipeUser(int userHandle) {
+ enforceSystemOrRoot("Only the system can wipe users");
+ // TODO:
+ }
+
+ /**
+ * Enforces that only the system UID or root's UID can call a method exposed
+ * via Binder.
+ *
+ * @param message used as message if SecurityException is thrown
+ * @throws SecurityException if the caller is not system or root
+ */
+ private static final void enforceSystemOrRoot(String message) {
+ final int uid = Binder.getCallingUid();
+ if (uid != Process.SYSTEM_UID && uid != 0) {
+ throw new SecurityException(message);
+ }
+ }
+
private ParcelFileDescriptor updateIconBitmapLocked(UserInfo info) {
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
@@ -184,6 +264,7 @@
}
private void readUserListLocked() {
+ mGuestEnabled = false;
if (!mUserListFile.exists()) {
fallbackToSingleUserLocked();
return;
@@ -212,6 +293,9 @@
if (user != null) {
mUsers.put(user.id, user);
}
+ if (user.isGuest()) {
+ mGuestEnabled = true;
+ }
}
}
updateUserIdsLocked();
@@ -389,7 +473,9 @@
return null;
}
+ @Override
public UserInfo createUser(String name, int flags) {
+ enforceSystemOrRoot("Only the system can create users");
int userId = getNextAvailableId();
UserInfo userInfo = new UserInfo(userId, name, null, flags);
File userPath = new File(mBaseUserPath, Integer.toString(userId));
@@ -402,6 +488,11 @@
writeUserLocked(userInfo);
updateUserIdsLocked();
}
+ if (userInfo != null) {
+ Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
+ addedIntent.putExtra(Intent.EXTRA_USERID, userInfo.id);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+ }
return userInfo;
}
@@ -410,27 +501,37 @@
* after the user's processes have been terminated.
* @param id the user's id
*/
- public boolean removeUser(int id) {
+ public boolean removeUser(int userHandle) {
+ enforceSystemOrRoot("Only the system can remove users");
synchronized (mUsers) {
- return removeUserLocked(id);
+ return removeUserLocked(userHandle);
}
}
- private boolean removeUserLocked(int id) {
- // Remove from the list
- UserInfo userInfo = mUsers.get(id);
- if (userInfo != null) {
- // Remove this user from the list
- mUsers.remove(id);
- // Remove user file
- File userFile = new File(mUsersDir, id + ".xml");
- userFile.delete();
- // Update the user list
- writeUserListLocked();
- updateUserIdsLocked();
- return true;
+ private boolean removeUserLocked(int userHandle) {
+ final UserInfo user = mUsers.get(userHandle);
+ if (userHandle == 0 || user == null) {
+ return false;
}
- return false;
+
+ mPm.cleanUpUser(userHandle);
+
+ // Remove this user from the list
+ mUsers.remove(userHandle);
+ // Remove user file
+ File userFile = new File(mUsersDir, userHandle + ".xml");
+ userFile.delete();
+ // Update the user list
+ writeUserListLocked();
+ updateUserIdsLocked();
+
+ // Let other services shutdown any activity
+ Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
+ addedIntent.putExtra(Intent.EXTRA_USERID, userHandle);
+ mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_ACCOUNTS);
+
+ removePackageFolders(userHandle);
+ return true;
}
public void installPackageForAllUsers(String packageName, int uid) {