am ba94170a: Merge "Some clean up of app install and user management." into jb-mr1-dev

* commit 'ba94170a7a4f78d68fe228e9ee35ed82c4de09c8':
  Some clean up of app install and user management.
This commit is contained in:
Dianne Hackborn
2012-08-24 18:05:58 -07:00
committed by Android Git Automerger
5 changed files with 192 additions and 186 deletions

View File

@@ -331,12 +331,16 @@ public abstract class RegisteredServicesCache<V> {
notifyListener(v1, true /* removed */); notifyListener(v1, true /* removed */);
} }
if (changes.length() > 0) { if (changes.length() > 0) {
Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " + if (Log.isLoggable(TAG, Log.VERBOSE)) {
serviceInfos.size() + " services:\n" + changes); Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
serviceInfos.size() + " services:\n" + changes);
}
writePersistentServicesLocked(); writePersistentServicesLocked();
} else { } else {
Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " + if (Log.isLoggable(TAG, Log.VERBOSE)) {
serviceInfos.size() + " services unchanged"); Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
serviceInfos.size() + " services unchanged");
}
} }
mPersistentServicesFileDidNotExist = false; mPersistentServicesFileDidNotExist = false;
} }

View File

@@ -197,7 +197,7 @@ class ServerThread extends Thread {
Slog.i(TAG, "User Service"); Slog.i(TAG, "User Service");
ServiceManager.addService(Context.USER_SERVICE, ServiceManager.addService(Context.USER_SERVICE,
UserManagerService.getInstance(context)); UserManagerService.getInstance());
mContentResolver = context.getContentResolver(); mContentResolver = context.getContentResolver();

View File

@@ -950,8 +950,8 @@ public class PackageManagerService extends IPackageManager.Stub {
mUserAppDataDir = new File(dataDir, "user"); mUserAppDataDir = new File(dataDir, "user");
mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
sUserManager = UserManagerService.getInstance(context); sUserManager = new UserManagerService(context, this,
sUserManager.setInstaller(this, mInstaller); mInstallLock, mPackages);
readPermissions(); readPermissions();
@@ -1145,8 +1145,7 @@ public class PackageManagerService extends IPackageManager.Stub {
String msg = "System package " + ps.name String msg = "System package " + ps.name
+ " no longer exists; wiping its data"; + " no longer exists; wiping its data";
reportSettingsProblem(Log.WARN, msg); reportSettingsProblem(Log.WARN, msg);
mInstaller.remove(ps.name, 0); removeDataDirsLI(ps.name);
sUserManager.removePackageForAllUsers(ps.name);
} else { } else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name); final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) { if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
@@ -1195,9 +1194,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (deletedPkg == null) { if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName msg = "Updated system package " + deletedAppName
+ " no longer exists; wiping its data"; + " no longer exists; wiping its data";
removeDataDirsLI(deletedAppName);
mInstaller.remove(deletedAppName, 0);
sUserManager.removePackageForAllUsers(deletedAppName);
} else { } else {
msg = "Updated system app + " + deletedAppName msg = "Updated system app + " + deletedAppName
+ " no longer present; removing system privileges for " + " no longer present; removing system privileges for "
@@ -1332,13 +1329,7 @@ public class PackageManagerService extends IPackageManager.Stub {
void cleanupInstallFailedPackage(PackageSetting ps) { void cleanupInstallFailedPackage(PackageSetting ps) {
Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name); Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
int retCode = mInstaller.remove(ps.name, 0); removeDataDirsLI(ps.name);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove app data directory for package: "
+ ps.name + ", retcode=" + retCode);
} else {
sUserManager.removePackageForAllUsers(ps.name);
}
if (ps.codePath != null) { if (ps.codePath != null) {
if (!ps.codePath.delete()) { if (!ps.codePath.delete()) {
Slog.w(TAG, "Unable to remove old code file: " + ps.codePath); Slog.w(TAG, "Unable to remove old code file: " + ps.codePath);
@@ -1818,9 +1809,11 @@ public class PackageManagerService extends IPackageManager.Stub {
public void run() { public void run() {
mHandler.removeCallbacks(this); mHandler.removeCallbacks(this);
int retCode = -1; int retCode = -1;
retCode = mInstaller.freeCache(freeStorageSize); synchronized (mInstallLock) {
if (retCode < 0) { retCode = mInstaller.freeCache(freeStorageSize);
Slog.w(TAG, "Couldn't clear application caches"); if (retCode < 0) {
Slog.w(TAG, "Couldn't clear application caches");
}
} }
if (observer != null) { if (observer != null) {
try { try {
@@ -1841,9 +1834,11 @@ public class PackageManagerService extends IPackageManager.Stub {
public void run() { public void run() {
mHandler.removeCallbacks(this); mHandler.removeCallbacks(this);
int retCode = -1; int retCode = -1;
retCode = mInstaller.freeCache(freeStorageSize); synchronized (mInstallLock) {
if (retCode < 0) { retCode = mInstaller.freeCache(freeStorageSize);
Slog.w(TAG, "Couldn't clear application caches"); if (retCode < 0) {
Slog.w(TAG, "Couldn't clear application caches");
}
} }
if(pi != null) { if(pi != null) {
try { try {
@@ -2994,7 +2989,9 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
ProviderInfo info = PackageParser.generateProviderInfo(p, flags, ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
ps.readUserState(userId), userId); ps.readUserState(userId), userId);
finalList.add(info); if (info != null) {
finalList.add(info);
}
} }
} }
} }
@@ -3027,8 +3024,11 @@ public class PackageManagerService extends IPackageManager.Stub {
final PackageParser.Instrumentation p = i.next(); final PackageParser.Instrumentation p = i.next();
if (targetPackage == null if (targetPackage == null
|| targetPackage.equals(p.info.targetPackage)) { || targetPackage.equals(p.info.targetPackage)) {
finalList.add(PackageParser.generateInstrumentationInfo(p, InstrumentationInfo ii = PackageParser.generateInstrumentationInfo(p,
flags)); flags);
if (ii != null) {
finalList.add(ii);
}
} }
} }
} }
@@ -3189,7 +3189,7 @@ public class PackageManagerService extends IPackageManager.Stub {
InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps), InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
synchronized (mInstaller) { synchronized (mInstallLock) {
args.cleanUpResourcesLI(); args.cleanUpResourcesLI();
} }
synchronized (mPackages) { synchronized (mPackages) {
@@ -3245,7 +3245,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " better than installed " + ps.versionCode); + " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps), InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString); ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
synchronized (mInstaller) { synchronized (mInstallLock) {
args.cleanUpResourcesLI(); args.cleanUpResourcesLI();
} }
} }
@@ -3479,6 +3479,36 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
} }
private int createDataDirsLI(String packageName, int uid) {
int[] users = sUserManager.getUserIds();
int res = mInstaller.install(packageName, uid, uid);
if (res < 0) {
return res;
}
for (int user : users) {
if (user != 0) {
res = mInstaller.createUserData(packageName,
UserHandle.getUid(user, uid), user);
if (res < 0) {
return res;
}
}
}
return res;
}
private int removeDataDirsLI(String packageName) {
int[] users = sUserManager.getUserIds();
int res = 0;
for (int user : users) {
int resInner = mInstaller.remove(packageName, user);
if (resInner < 0) {
res = resInner;
}
}
return res;
}
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, long currentTime, UserHandle user) { int parseFlags, int scanMode, long currentTime, UserHandle user) {
File scanFile = new File(pkg.mScanPath); File scanFile = new File(pkg.mScanPath);
@@ -3831,11 +3861,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|| (scanMode&SCAN_BOOTING) != 0)) { || (scanMode&SCAN_BOOTING) != 0)) {
// If this is a system app, we can at least delete its // If this is a system app, we can at least delete its
// current data so the application will still work. // current data so the application will still work.
int ret = mInstaller.remove(pkgName, 0); int ret = removeDataDirsLI(pkgName);
if (ret >= 0) { if (ret >= 0) {
// TODO: Kill the processes first // TODO: Kill the processes first
// Remove the data directories for all users
sUserManager.removePackageForAllUsers(pkgName);
// Old data gone! // Old data gone!
String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0 String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
? "System package " : "Third party package "; ? "System package " : "Third party package ";
@@ -3847,8 +3875,7 @@ public class PackageManagerService extends IPackageManager.Stub {
recovered = true; recovered = true;
// And now re-install the app. // And now re-install the app.
ret = mInstaller.install(pkgName, pkg.applicationInfo.uid, ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
pkg.applicationInfo.uid);
if (ret == -1) { if (ret == -1) {
// Ack should not happen! // Ack should not happen!
msg = prefix + pkg.packageName msg = prefix + pkg.packageName
@@ -3857,9 +3884,6 @@ public class PackageManagerService extends IPackageManager.Stub {
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null; return null;
} }
// Create data directories for all users
sUserManager.installPackageForAllUsers(pkgName,
pkg.applicationInfo.uid);
} }
if (!recovered) { if (!recovered) {
mHasSystemUidErrors = true; mHasSystemUidErrors = true;
@@ -3897,15 +3921,12 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.v(TAG, "Want this data dir: " + dataPath); Log.v(TAG, "Want this data dir: " + dataPath);
} }
//invoke installer to do the actual installation //invoke installer to do the actual installation
int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid, int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid);
pkg.applicationInfo.uid);
if (ret < 0) { if (ret < 0) {
// Error from installer // Error from installer
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null; return null;
} }
// Create data directories for all users
sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);
if (dataPath.exists()) { if (dataPath.exists()) {
pkg.applicationInfo.dataDir = dataPath.getPath(); pkg.applicationInfo.dataDir = dataPath.getPath();
@@ -5078,6 +5099,9 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags, ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
ps.readUserState(userId), userId); ps.readUserState(userId), userId);
if (si == null) {
return null;
}
final ResolveInfo res = new ResolveInfo(); final ResolveInfo res = new ResolveInfo();
res.serviceInfo = si; res.serviceInfo = si;
if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) { if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
@@ -7819,15 +7843,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
} }
if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) { if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
int retCode = mInstaller.remove(packageName, 0); removeDataDirsLI(packageName);
if (retCode < 0) {
Slog.w(TAG, "Couldn't remove app data or cache directory for package: "
+ packageName + ", retcode=" + retCode);
// we don't consider this to be a failure of the core package deletion
} else {
// TODO: Kill the processes first
sUserManager.removePackageForAllUsers(packageName);
}
schedulePackageCleaning(packageName, UserHandle.USER_ALL, true); schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
} }
// writer // writer
@@ -9742,15 +9758,36 @@ public class PackageManagerService extends IPackageManager.Stub {
} }
/** Called by UserManagerService */ /** Called by UserManagerService */
void cleanUpUser(int userHandle) { void cleanUpUserLILPw(int userHandle) {
// Disable all the packages for the user first // Disable all the packages for the user first
synchronized (mPackages) { Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet();
Set<Entry<String, PackageSetting>> entries = mSettings.mPackages.entrySet(); for (Entry<String, PackageSetting> entry : entries) {
for (Entry<String, PackageSetting> entry : entries) { entry.getValue().removeUser(userHandle);
entry.getValue().removeUser(userHandle); }
if (mDirtyUsers.remove(userHandle));
mSettings.removeUserLPr(userHandle);
if (mInstaller != null) {
// Technically, we shouldn't be doing this with the package lock
// held. However, this is very rare, and there is already so much
// other disk I/O going on, that we'll let it slide for now.
mInstaller.removeUserDataDirs(userHandle);
}
}
/** Called by UserManagerService */
void createNewUserLILPw(int userHandle, File path) {
if (mInstaller != null) {
path.mkdir();
FileUtils.setPermissions(path.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
| FileUtils.S_IXOTH, -1, -1);
for (PackageSetting ps : mSettings.mPackages.values()) {
// Only system apps are initially installed.
ps.setInstalled((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0, userHandle);
// Need to create a data directory for all apps under this user.
mInstaller.createUserData(ps.name,
UserHandle.getUid(userHandle, ps.appId), userHandle);
} }
if (mDirtyUsers.remove(userHandle)); mSettings.writePackageRestrictionsLPr(userHandle);
mSettings.removeUserLPr(userHandle);
} }
} }

View File

@@ -2476,7 +2476,7 @@ final class Settings {
private List<UserInfo> getAllUsers() { private List<UserInfo> getAllUsers() {
long id = Binder.clearCallingIdentity(); long id = Binder.clearCallingIdentity();
try { try {
return UserManagerService.getInstance(mContext).getUsers(); return UserManagerService.getInstance().getUsers();
} catch (NullPointerException npe) { } catch (NullPointerException npe) {
// packagemanager not yet initialized // packagemanager not yet initialized
} finally { } finally {

View File

@@ -25,7 +25,6 @@ import com.android.internal.util.FastXmlSerializer;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.os.Binder; import android.os.Binder;
@@ -34,10 +33,8 @@ import android.os.FileUtils;
import android.os.IUserManager; import android.os.IUserManager;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.Process; import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.AtomicFile; import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.Xml; import android.util.Xml;
@@ -72,59 +69,79 @@ public class UserManagerService extends IUserManager.Stub {
private static final String USER_LIST_FILENAME = "userlist.xml"; private static final String USER_LIST_FILENAME = "userlist.xml";
private static final String USER_PHOTO_FILENAME = "photo.png"; private static final String USER_PHOTO_FILENAME = "photo.png";
private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); private final Context mContext;
private final PackageManagerService mPm;
private final Object mInstallLock;
private final Object mPackagesLock;
private final File mUsersDir; private final File mUsersDir;
private final File mUserListFile; private final File mUserListFile;
private final File mBaseUserPath;
private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
private int[] mUserIds; private int[] mUserIds;
private boolean mGuestEnabled; private boolean mGuestEnabled;
private int mNextSerialNumber; private int mNextSerialNumber;
private Installer mInstaller;
private File mBaseUserPath;
private Context mContext;
private static UserManagerService sInstance; private static UserManagerService sInstance;
private PackageManagerService mPm;
public synchronized static UserManagerService getInstance(Context context) { public static UserManagerService getInstance() {
if (sInstance == null) { synchronized (UserManagerService.class) {
sInstance = new UserManagerService(context); return sInstance;
} }
return sInstance;
} }
/** /**
* Available for testing purposes. * Available for testing purposes.
*/ */
UserManagerService(File dataDir, File baseUserPath) { UserManagerService(File dataDir, File baseUserPath) {
mUsersDir = new File(dataDir, USER_INFO_DIR); this(null, null, new Object(), new Object(), dataDir, baseUserPath);
mUsersDir.mkdirs();
// Make zeroth user directory, for services to migrate their files to that location
File userZeroDir = new File(mUsersDir, "0");
userZeroDir.mkdirs();
mBaseUserPath = baseUserPath;
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
readUserList();
} }
public UserManagerService(Context context) { /**
this(Environment.getDataDirectory(), new File(Environment.getDataDirectory(), "user")); * Called by package manager to create the service. This is closely
mContext = context; * associated with the package manager, and the given lock is the
* package manager's own lock.
*/
UserManagerService(Context context, PackageManagerService pm,
Object installLock, Object packagesLock) {
this(context, pm, installLock, packagesLock,
Environment.getDataDirectory(),
new File(Environment.getDataDirectory(), "user"));
} }
void setInstaller(PackageManagerService pm, Installer installer) { /**
mInstaller = installer; * Available for testing purposes.
mPm = pm; */
private UserManagerService(Context context, PackageManagerService pm,
Object installLock, Object packagesLock,
File dataDir, File baseUserPath) {
synchronized (UserManagerService.class) {
mContext = context;
mPm = pm;
mInstallLock = installLock;
mPackagesLock = packagesLock;
mUsersDir = new File(dataDir, USER_INFO_DIR);
mUsersDir.mkdirs();
// Make zeroth user directory, for services to migrate their files to that location
File userZeroDir = new File(mUsersDir, "0");
userZeroDir.mkdirs();
mBaseUserPath = baseUserPath;
FileUtils.setPermissions(mUsersDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1, -1);
mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
readUserList();
sInstance = this;
}
} }
@Override @Override
public List<UserInfo> getUsers() { public List<UserInfo> getUsers() {
checkManageUsersPermission("query users"); checkManageUsersPermission("query users");
synchronized (mUsers) { synchronized (mPackagesLock) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) { for (int i = 0; i < mUsers.size(); i++) {
users.add(mUsers.valueAt(i)); users.add(mUsers.valueAt(i));
@@ -136,7 +153,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override @Override
public UserInfo getUserInfo(int userId) { public UserInfo getUserInfo(int userId) {
checkManageUsersPermission("query user"); checkManageUsersPermission("query user");
synchronized (mUsers) { synchronized (mPackagesLock) {
return getUserInfoLocked(userId); return getUserInfoLocked(userId);
} }
} }
@@ -149,7 +166,7 @@ public class UserManagerService extends IUserManager.Stub {
} }
public boolean exists(int userId) { public boolean exists(int userId) {
synchronized (mUsers) { synchronized (mPackagesLock) {
return ArrayUtils.contains(mUserIds, userId); return ArrayUtils.contains(mUserIds, userId);
} }
} }
@@ -157,7 +174,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override @Override
public void setUserName(int userId, String name) { public void setUserName(int userId, String name) {
checkManageUsersPermission("rename users"); checkManageUsersPermission("rename users");
synchronized (mUsers) { synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId); UserInfo info = mUsers.get(userId);
if (name != null && !name.equals(info.name)) { if (name != null && !name.equals(info.name)) {
info.name = name; info.name = name;
@@ -169,7 +186,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override @Override
public ParcelFileDescriptor setUserIcon(int userId) { public ParcelFileDescriptor setUserIcon(int userId) {
checkManageUsersPermission("update users"); checkManageUsersPermission("update users");
synchronized (mUsers) { synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId); UserInfo info = mUsers.get(userId);
if (info == null) return null; if (info == null) return null;
ParcelFileDescriptor fd = updateIconBitmapLocked(info); ParcelFileDescriptor fd = updateIconBitmapLocked(info);
@@ -183,7 +200,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override @Override
public void setGuestEnabled(boolean enable) { public void setGuestEnabled(boolean enable) {
checkManageUsersPermission("enable guest users"); checkManageUsersPermission("enable guest users");
synchronized (mUsers) { synchronized (mPackagesLock) {
if (mGuestEnabled != enable) { if (mGuestEnabled != enable) {
mGuestEnabled = enable; mGuestEnabled = enable;
// Erase any guest user that currently exists // Erase any guest user that currently exists
@@ -206,7 +223,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override @Override
public boolean isGuestEnabled() { public boolean isGuestEnabled() {
synchronized (mUsers) { synchronized (mPackagesLock) {
return mGuestEnabled; return mGuestEnabled;
} }
} }
@@ -262,13 +279,17 @@ public class UserManagerService extends IUserManager.Stub {
* @return the array of user ids. * @return the array of user ids.
*/ */
int[] getUserIds() { int[] getUserIds() {
synchronized (mUsers) { synchronized (mPackagesLock) {
return mUserIds; return mUserIds;
} }
} }
int[] getUserIdsLPr() {
return mUserIds;
}
private void readUserList() { private void readUserList() {
synchronized (mUsers) { synchronized (mPackagesLock) {
readUserListLocked(); readUserListLocked();
} }
} }
@@ -501,15 +522,15 @@ public class UserManagerService extends IUserManager.Stub {
int userId = getNextAvailableId(); int userId = getNextAvailableId();
UserInfo userInfo = new UserInfo(userId, name, null, flags); UserInfo userInfo = new UserInfo(userId, name, null, flags);
File userPath = new File(mBaseUserPath, Integer.toString(userId)); File userPath = new File(mBaseUserPath, Integer.toString(userId));
if (!createPackageFolders(userId, userPath)) { synchronized (mInstallLock) {
return null; synchronized (mPackagesLock) {
} userInfo.serialNumber = mNextSerialNumber++;
synchronized (mUsers) { mUsers.put(userId, userInfo);
userInfo.serialNumber = mNextSerialNumber++; writeUserListLocked();
mUsers.put(userId, userInfo); writeUserLocked(userInfo);
writeUserListLocked(); updateUserIdsLocked();
writeUserLocked(userInfo); mPm.createNewUserLILPw(userId, userPath);
updateUserIdsLocked(); }
} }
if (userInfo != null) { if (userInfo != null) {
Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED); Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
@@ -528,24 +549,37 @@ public class UserManagerService extends IUserManager.Stub {
*/ */
public boolean removeUser(int userHandle) { public boolean removeUser(int userHandle) {
checkManageUsersPermission("Only the system can remove users"); checkManageUsersPermission("Only the system can remove users");
boolean result; synchronized (mInstallLock) {
synchronized (mUsers) { synchronized (mPackagesLock) {
result = removeUserLocked(userHandle); final UserInfo user = mUsers.get(userHandle);
} if (userHandle == 0 || user == null) {
return false;
}
// Cleanup package manager settings // Cleanup package manager settings
mPm.cleanUpUser(userHandle); mPm.cleanUpUserLILPw(userHandle);
// Remove this user from the list
mUsers.remove(userHandle);
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
userFile.delete();
// Update the user list
writeUserListLocked();
updateUserIdsLocked();
}
}
// Let other services shutdown any activity // Let other services shutdown any activity
Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED); Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS); mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS);
return result; return true;
} }
@Override @Override
public int getUserSerialNumber(int userHandle) { public int getUserSerialNumber(int userHandle) {
synchronized (mUsers) { synchronized (mPackagesLock) {
if (!exists(userHandle)) return -1; if (!exists(userHandle)) return -1;
return getUserInfoLocked(userHandle).serialNumber; return getUserInfoLocked(userHandle).serialNumber;
} }
@@ -553,7 +587,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override @Override
public int getUserHandle(int userSerialNumber) { public int getUserHandle(int userSerialNumber) {
synchronized (mUsers) { synchronized (mPackagesLock) {
for (int userId : mUserIds) { for (int userId : mUserIds) {
if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId; if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId;
} }
@@ -562,53 +596,6 @@ public class UserManagerService extends IUserManager.Stub {
} }
} }
private boolean removeUserLocked(int userHandle) {
final UserInfo user = mUsers.get(userHandle);
if (userHandle == 0 || user == null) {
return false;
}
// Remove this user from the list
mUsers.remove(userHandle);
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
userFile.delete();
// Update the user list
writeUserListLocked();
updateUserIdsLocked();
removePackageFolders(userHandle);
return true;
}
public void installPackageForAllUsers(String packageName, int uid) {
for (int userId : mUserIds) {
// Don't do it for the primary user, it will become recursive.
if (userId == 0)
continue;
mInstaller.createUserData(packageName, UserHandle.getUid(userId, uid),
userId);
}
}
public void clearUserDataForAllUsers(String packageName) {
for (int userId : mUserIds) {
// Don't do it for the primary user, it will become recursive.
if (userId == 0)
continue;
mInstaller.clearUserData(packageName, userId);
}
}
public void removePackageForAllUsers(String packageName) {
for (int userId : mUserIds) {
// Don't do it for the primary user, it will become recursive.
if (userId == 0)
continue;
mInstaller.remove(packageName, userId);
}
}
/** /**
* Caches the list of user ids in an array, adjusting the array size when necessary. * Caches the list of user ids in an array, adjusting the array size when necessary.
*/ */
@@ -627,7 +614,7 @@ public class UserManagerService extends IUserManager.Stub {
* @return * @return
*/ */
private int getNextAvailableId() { private int getNextAvailableId() {
synchronized (mUsers) { synchronized (mPackagesLock) {
int i = 0; int i = 0;
while (i < Integer.MAX_VALUE) { while (i < Integer.MAX_VALUE) {
if (mUsers.indexOfKey(i) < 0) { if (mUsers.indexOfKey(i) < 0) {
@@ -638,26 +625,4 @@ public class UserManagerService extends IUserManager.Stub {
return i; return i;
} }
} }
private boolean createPackageFolders(int id, File userPath) {
// mInstaller may not be available for unit-tests.
if (mInstaller == null) return true;
// Create the user path
userPath.mkdir();
FileUtils.setPermissions(userPath.toString(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
| FileUtils.S_IXOTH, -1, -1);
mInstaller.cloneUserData(0, id, false);
return true;
}
boolean removePackageFolders(int id) {
// mInstaller may not be available for unit-tests.
if (mInstaller == null) return true;
mInstaller.removeUserDataDirs(id);
return true;
}
} }