UserManagerServicepublic class UserManagerService extends IUserManager.Stub
Fields Summary |
---|
private static final String | LOG_TAG | private static final boolean | DBG | private static final String | TAG_NAME | private static final String | ATTR_FLAGS | private static final String | ATTR_ICON_PATH | private static final String | ATTR_ID | private static final String | ATTR_CREATION_TIME | private static final String | ATTR_LAST_LOGGED_IN_TIME | private static final String | ATTR_SALT | private static final String | ATTR_PIN_HASH | private static final String | ATTR_FAILED_ATTEMPTS | private static final String | ATTR_LAST_RETRY_MS | private static final String | ATTR_SERIAL_NO | private static final String | ATTR_NEXT_SERIAL_NO | private static final String | ATTR_PARTIAL | private static final String | ATTR_GUEST_TO_REMOVE | private static final String | ATTR_USER_VERSION | private static final String | ATTR_PROFILE_GROUP_ID | private static final String | TAG_GUEST_RESTRICTIONS | private static final String | TAG_USERS | private static final String | TAG_USER | private static final String | TAG_RESTRICTIONS | private static final String | TAG_ENTRY | private static final String | TAG_VALUE | private static final String | ATTR_KEY | private static final String | ATTR_VALUE_TYPE | private static final String | ATTR_MULTIPLE | private static final String | ATTR_TYPE_STRING_ARRAY | private static final String | ATTR_TYPE_STRING | private static final String | ATTR_TYPE_BOOLEAN | private static final String | ATTR_TYPE_INTEGER | private static final String | USER_INFO_DIR | private static final String | USER_LIST_FILENAME | private static final String | USER_PHOTO_FILENAME | private static final String | RESTRICTIONS_FILE_PREFIX | private static final String | XML_SUFFIX | private static final int | MIN_USER_ID | private static final int | USER_VERSION | private static final long | EPOCH_PLUS_30_YEARS | private static final int | BACKOFF_INC_INTERVAL | private static final int | MAX_MANAGED_PROFILES | private static final int[] | BACKOFF_TIMES | private final android.content.Context | mContext | private final PackageManagerService | mPm | private final Object | mInstallLock | private final Object | mPackagesLock | private final android.os.Handler | mHandler | private final File | mUsersDir | private final File | mUserListFile | private final File | mBaseUserPath | private final android.util.SparseArray | mUsers | private final android.util.SparseArray | mUserRestrictions | private final android.os.Bundle | mGuestRestrictions | private final android.util.SparseArray | mRestrictionsPinStates | private final android.util.SparseBooleanArray | mRemovingUserIdsSet of user IDs being actively removed. Removed IDs linger in this set
for several seconds to work around a VFS caching issue. | private int[] | mUserIds | private int | mNextSerialNumber | private int | mUserVersion | private com.android.internal.app.IAppOpsService | mAppOpsService | private static UserManagerService | sInstance |
Constructors Summary |
---|
UserManagerService(File dataDir, File baseUserPath)Available for testing purposes.
this(null, null, new Object(), new Object(), dataDir, baseUserPath);
| UserManagerService(android.content.Context context, PackageManagerService pm, Object installLock, Object packagesLock)Called by package manager to create the service. This is closely
associated with the package manager, and the given lock is the
package manager's own lock.
this(context, pm, installLock, packagesLock,
Environment.getDataDirectory(),
new File(Environment.getDataDirectory(), "user"));
| private UserManagerService(android.content.Context context, PackageManagerService pm, Object installLock, Object packagesLock, File dataDir, File baseUserPath)Available for testing purposes.
mContext = context;
mPm = pm;
mInstallLock = installLock;
mPackagesLock = packagesLock;
mHandler = new Handler();
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
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);
initDefaultGuestRestrictions();
readUserListLocked();
// Prune out any partially created/partially removed users.
ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
for (int i = 0; i < mUsers.size(); i++) {
UserInfo ui = mUsers.valueAt(i);
if ((ui.partial || ui.guestToRemove) && i != 0) {
partials.add(ui);
}
}
for (int i = 0; i < partials.size(); i++) {
UserInfo ui = partials.get(i);
Slog.w(LOG_TAG, "Removing partially created user #" + i
+ " (name=" + ui.name + ")");
removeUserStateLocked(ui.id);
}
sInstance = this;
}
}
|
Methods Summary |
---|
private static final void | checkManageUsersPermission(java.lang.String message)Enforces that only the system UID or root's UID or apps that have the
{@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
permission can make certain calls to the UserManager.
final int uid = Binder.getCallingUid();
if (uid != Process.SYSTEM_UID && uid != 0
&& ActivityManager.checkComponentPermission(
android.Manifest.permission.MANAGE_USERS,
uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("You need MANAGE_USERS permission to: " + message);
}
| public int | checkRestrictionsChallenge(java.lang.String pin)
checkManageUsersPermission("Only system can verify the restrictions pin");
int userId = UserHandle.getCallingUserId();
synchronized (mPackagesLock) {
RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
// If there's no pin set, return error code
if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
return UserManager.PIN_VERIFICATION_FAILED_NOT_SET;
} else if (pin == null) {
// If just checking if user can be prompted, return remaining time
int waitTime = getRemainingTimeForPinAttempt(pinState);
Slog.d(LOG_TAG, "Remaining waittime peek=" + waitTime);
return waitTime;
} else {
int waitTime = getRemainingTimeForPinAttempt(pinState);
Slog.d(LOG_TAG, "Remaining waittime=" + waitTime);
if (waitTime > 0) {
return waitTime;
}
if (passwordToHash(pin, pinState.salt).equals(pinState.pinHash)) {
pinState.failedAttempts = 0;
writeUserLocked(mUsers.get(userId));
return UserManager.PIN_VERIFICATION_SUCCESS;
} else {
pinState.failedAttempts++;
pinState.lastAttemptTime = System.currentTimeMillis();
writeUserLocked(mUsers.get(userId));
return waitTime;
}
}
}
| private void | cleanAppRestrictions(int userId)Removes all the restrictions files (res_) for a given user.
Does not do any permissions checking.
synchronized (mPackagesLock) {
File dir = Environment.getUserSystemDirectory(userId);
String[] files = dir.list();
if (files == null) return;
for (String fileName : files) {
if (fileName.startsWith(RESTRICTIONS_FILE_PREFIX)) {
File resFile = new File(dir, fileName);
if (resFile.exists()) {
resFile.delete();
}
}
}
}
| private void | cleanAppRestrictionsForPackage(java.lang.String pkg, int userId)Removes the app restrictions file for a specific package and user id, if it exists.
synchronized (mPackagesLock) {
File dir = Environment.getUserSystemDirectory(userId);
File resFile = new File(dir, packageToRestrictionsFileName(pkg));
if (resFile.exists()) {
resFile.delete();
}
}
| public android.content.pm.UserInfo | createProfileForUser(java.lang.String name, int flags, int userId)
checkManageUsersPermission("Only the system can create users");
if (userId != UserHandle.USER_OWNER) {
Slog.w(LOG_TAG, "Only user owner can have profiles");
return null;
}
return createUserInternal(name, flags, userId);
| public android.content.pm.UserInfo | createUser(java.lang.String name, int flags)
checkManageUsersPermission("Only the system can create users");
return createUserInternal(name, flags, UserHandle.USER_NULL);
| private android.content.pm.UserInfo | createUserInternal(java.lang.String name, int flags, int parentId)
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
UserManager.DISALLOW_ADD_USER, false)) {
Log.w(LOG_TAG, "Cannot add user. DISALLOW_ADD_USER is enabled.");
return null;
}
final boolean isGuest = (flags & UserInfo.FLAG_GUEST) != 0;
final long ident = Binder.clearCallingIdentity();
UserInfo userInfo = null;
try {
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
UserInfo parent = null;
if (parentId != UserHandle.USER_NULL) {
parent = getUserInfoLocked(parentId);
if (parent == null) return null;
}
// If we're not adding a guest user and the limit has been reached,
// cannot add a user.
if (!isGuest && isUserLimitReachedLocked()) {
return null;
}
// If we're adding a guest and there already exists one, bail.
if (isGuest && findCurrentGuestUserLocked() != null) {
return null;
}
// Limit number of managed profiles that can be created
if ((flags & UserInfo.FLAG_MANAGED_PROFILE) != 0
&& numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true)
>= MAX_MANAGED_PROFILES) {
return null;
}
int userId = getNextAvailableIdLocked();
userInfo = new UserInfo(userId, name, null, flags);
File userPath = new File(mBaseUserPath, Integer.toString(userId));
userInfo.serialNumber = mNextSerialNumber++;
long now = System.currentTimeMillis();
userInfo.creationTime = (now > EPOCH_PLUS_30_YEARS) ? now : 0;
userInfo.partial = true;
Environment.getUserSystemDirectory(userInfo.id).mkdirs();
mUsers.put(userId, userInfo);
writeUserListLocked();
if (parent != null) {
if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
parent.profileGroupId = parent.id;
writeUserLocked(parent);
}
userInfo.profileGroupId = parent.profileGroupId;
}
writeUserLocked(userInfo);
mPm.createNewUserLILPw(userId, userPath);
userInfo.partial = false;
writeUserLocked(userInfo);
updateUserIdsLocked();
Bundle restrictions = new Bundle();
mUserRestrictions.append(userId, restrictions);
}
}
if (userInfo != null) {
Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id);
mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
android.Manifest.permission.MANAGE_USERS);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
return userInfo;
| protected void | dump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump UserManager from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
+ " without permission "
+ android.Manifest.permission.DUMP);
return;
}
long now = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
synchronized (mPackagesLock) {
pw.println("Users:");
for (int i = 0; i < mUsers.size(); i++) {
UserInfo user = mUsers.valueAt(i);
if (user == null) continue;
pw.print(" "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber);
if (mRemovingUserIds.get(mUsers.keyAt(i))) pw.print(" <removing> ");
if (user.partial) pw.print(" <partial>");
pw.println();
pw.print(" Created: ");
if (user.creationTime == 0) {
pw.println("<unknown>");
} else {
sb.setLength(0);
TimeUtils.formatDuration(now - user.creationTime, sb);
sb.append(" ago");
pw.println(sb);
}
pw.print(" Last logged in: ");
if (user.lastLoggedInTime == 0) {
pw.println("<unknown>");
} else {
sb.setLength(0);
TimeUtils.formatDuration(now - user.lastLoggedInTime, sb);
sb.append(" ago");
pw.println(sb);
}
}
}
| public boolean | exists(int userId)
synchronized (mPackagesLock) {
return ArrayUtils.contains(mUserIds, userId);
}
| private void | fallbackToSingleUserLocked()
// Create the primary user
UserInfo primary = new UserInfo(UserHandle.USER_OWNER,
mContext.getResources().getString(com.android.internal.R.string.owner_name), null,
UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED);
mUsers.put(0, primary);
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;
Bundle restrictions = new Bundle();
mUserRestrictions.append(UserHandle.USER_OWNER, restrictions);
updateUserIdsLocked();
initDefaultGuestRestrictions();
writeUserListLocked();
writeUserLocked(primary);
| private android.content.pm.UserInfo | findCurrentGuestUserLocked()Find the current guest user. If the Guest user is partial,
then do not include it in the results as it is about to die.
This is different than {@link #numberOfUsersOfTypeLocked(int, boolean)} due to
the special handling of Guests being removed.
final int size = mUsers.size();
for (int i = 0; i < size; i++) {
final UserInfo user = mUsers.valueAt(i);
if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
return user;
}
}
return null;
| void | finishRemoveUser(int userHandle)
if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle);
// 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.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);
}
| public android.os.Bundle | getApplicationRestrictions(java.lang.String packageName)
return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
| public android.os.Bundle | getApplicationRestrictionsForUser(java.lang.String packageName, int userId)
if (UserHandle.getCallingUserId() != userId
|| !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
checkManageUsersPermission("Only system can get restrictions for other users/apps");
}
synchronized (mPackagesLock) {
// Read the restrictions from XML
return readApplicationRestrictionsLocked(packageName, userId);
}
| public android.os.Bundle | getDefaultGuestRestrictions()
checkManageUsersPermission("getDefaultGuestRestrictions");
synchronized (mPackagesLock) {
return new Bundle(mGuestRestrictions);
}
| public static com.android.server.pm.UserManagerService | getInstance()
synchronized (UserManagerService.class) {
return sInstance;
}
| private int | getNextAvailableIdLocked()Returns the next available user id, filling in any holes in the ids.
TODO: May not be a good idea to recycle ids, in case it results in confusion
for data and battery stats collection, or unexpected cross-talk.
synchronized (mPackagesLock) {
int i = MIN_USER_ID;
while (i < Integer.MAX_VALUE) {
if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
break;
}
i++;
}
return i;
}
| public android.content.pm.UserInfo | getProfileParent(int userHandle)
checkManageUsersPermission("get the profile parent");
synchronized (mPackagesLock) {
UserInfo profile = getUserInfoLocked(userHandle);
if (profile == null) {
return null;
}
int parentUserId = profile.profileGroupId;
if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
return null;
} else {
return getUserInfoLocked(parentUserId);
}
}
| public java.util.List | getProfiles(int userId, boolean enabledOnly)
if (userId != UserHandle.getCallingUserId()) {
checkManageUsersPermission("getting profiles related to user " + userId);
}
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mPackagesLock) {
return getProfilesLocked(userId, enabledOnly);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
| private java.util.List | getProfilesLocked(int userId, boolean enabledOnly)Assume permissions already checked and caller's identity cleared
UserInfo user = getUserInfoLocked(userId);
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
if (user == null) {
// Probably a dying user
return users;
}
for (int i = 0; i < mUsers.size(); i++) {
UserInfo profile = mUsers.valueAt(i);
if (!isProfileOf(user, profile)) {
continue;
}
if (enabledOnly && !profile.isEnabled()) {
continue;
}
if (mRemovingUserIds.get(profile.id)) {
continue;
}
users.add(profile);
}
return users;
| private int | getRemainingTimeForPinAttempt(com.android.server.pm.UserManagerService$RestrictionsPinState pinState)
int backoffIndex = Math.min(pinState.failedAttempts / BACKOFF_INC_INTERVAL,
BACKOFF_TIMES.length - 1);
int backoffTime = (pinState.failedAttempts % BACKOFF_INC_INTERVAL) == 0 ?
BACKOFF_TIMES[backoffIndex] : 0;
return (int) Math.max(backoffTime + pinState.lastAttemptTime - System.currentTimeMillis(),
0);
| private int | getUidForPackage(java.lang.String packageName)
long ident = Binder.clearCallingIdentity();
try {
return mContext.getPackageManager().getApplicationInfo(packageName,
PackageManager.GET_UNINSTALLED_PACKAGES).uid;
} catch (NameNotFoundException nnfe) {
return -1;
} finally {
Binder.restoreCallingIdentity(ident);
}
| public int | getUserHandle(int userSerialNumber)
synchronized (mPackagesLock) {
for (int userId : mUserIds) {
if (getUserInfoLocked(userId).serialNumber == userSerialNumber) return userId;
}
// Not found
return -1;
}
| public android.graphics.Bitmap | getUserIcon(int userId)
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId);
return null;
}
int callingGroupId = mUsers.get(UserHandle.getCallingUserId()).profileGroupId;
if (callingGroupId == UserInfo.NO_PROFILE_GROUP_ID
|| callingGroupId != info.profileGroupId) {
checkManageUsersPermission("get the icon of a user who is not related");
}
if (info.iconPath == null) {
return null;
}
return BitmapFactory.decodeFile(info.iconPath);
}
| public int[] | getUserIds()Returns an array of user ids. This array is cached here for quick access, so do not modify or
cache it elsewhere.
synchronized (mPackagesLock) {
return mUserIds;
}
| int[] | getUserIdsLPr()
return mUserIds;
| public android.content.pm.UserInfo | getUserInfo(int userId)
checkManageUsersPermission("query user");
synchronized (mPackagesLock) {
return getUserInfoLocked(userId);
}
| private android.content.pm.UserInfo | getUserInfoLocked(int userId)
UserInfo ui = mUsers.get(userId);
// If it is partial and not in the process of being removed, return as unknown user.
if (ui != null && ui.partial && !mRemovingUserIds.get(userId)) {
Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId);
return null;
}
return ui;
| public android.os.Bundle | getUserRestrictions(int userId)
// checkManageUsersPermission("getUserRestrictions");
synchronized (mPackagesLock) {
Bundle restrictions = mUserRestrictions.get(userId);
return restrictions != null ? new Bundle(restrictions) : new Bundle();
}
| public int | getUserSerialNumber(int userHandle)
synchronized (mPackagesLock) {
if (!exists(userHandle)) return -1;
return getUserInfoLocked(userHandle).serialNumber;
}
| public java.util.List | getUsers(boolean excludeDying)
checkManageUsersPermission("query users");
synchronized (mPackagesLock) {
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) {
UserInfo ui = mUsers.valueAt(i);
if (ui.partial) {
continue;
}
if (!excludeDying || !mRemovingUserIds.get(ui.id)) {
users.add(ui);
}
}
return users;
}
| public boolean | hasRestrictionsChallenge()
int userId = UserHandle.getCallingUserId();
synchronized (mPackagesLock) {
return hasRestrictionsPinLocked(userId);
}
| private boolean | hasRestrictionsPinLocked(int userId)
RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
return false;
}
return true;
| public boolean | hasUserRestriction(java.lang.String restrictionKey, int userId)
synchronized (mPackagesLock) {
Bundle restrictions = mUserRestrictions.get(userId);
return restrictions != null ? restrictions.getBoolean(restrictionKey) : false;
}
| private void | initDefaultGuestRestrictions()If default guest restrictions haven't been initialized yet, add the basic
restrictions.
if (mGuestRestrictions.isEmpty()) {
mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true);
mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true);
}
| private boolean | isPackageInstalled(java.lang.String pkg, int userId)
final ApplicationInfo info = mPm.getApplicationInfo(pkg,
PackageManager.GET_UNINSTALLED_PACKAGES,
userId);
if (info == null || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
return false;
}
return true;
| private boolean | isProfileOf(android.content.pm.UserInfo user, android.content.pm.UserInfo profile)
return user.id == profile.id ||
(user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
&& user.profileGroupId == profile.profileGroupId);
| public boolean | isRestricted()
synchronized (mPackagesLock) {
return getUserInfoLocked(UserHandle.getCallingUserId()).isRestricted();
}
| private boolean | isUserLimitReachedLocked()Check if we've hit the limit of how many users can be created.
int aliveUserCount = 0;
final int totalUserCount = mUsers.size();
// Skip over users being removed
for (int i = 0; i < totalUserCount; i++) {
UserInfo user = mUsers.valueAt(i);
if (!mRemovingUserIds.get(user.id)
&& !user.isGuest() && !user.partial) {
aliveUserCount++;
}
}
return aliveUserCount >= UserManager.getMaxSupportedUsers();
| public void | makeInitialized(int userId)
checkManageUsersPermission("makeInitialized");
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "makeInitialized: unknown user #" + userId);
}
if ((info.flags&UserInfo.FLAG_INITIALIZED) == 0) {
info.flags |= UserInfo.FLAG_INITIALIZED;
writeUserLocked(info);
}
}
| public boolean | markGuestForDeletion(int userHandle)Mark this guest user for deletion to allow us to create another guest
and switch to that user before actually removing this guest.
checkManageUsersPermission("Only the system can remove users");
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
UserManager.DISALLOW_REMOVE_USER, false)) {
Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
return false;
}
long ident = Binder.clearCallingIdentity();
try {
final UserInfo user;
synchronized (mPackagesLock) {
user = mUsers.get(userHandle);
if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
return false;
}
if (!user.isGuest()) {
return false;
}
// We set this to a guest user that is to be removed. This is a temporary state
// where we are allowed to add new Guest users, even if this one is still not
// removed. This user will still show up in getUserInfo() calls.
// If we don't get around to removing this Guest user, it will be purged on next
// startup.
user.guestToRemove = true;
// Mark it as disabled, so that it isn't returned any more when
// profiles are queried.
user.flags |= UserInfo.FLAG_DISABLED;
writeUserLocked(user);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
return true;
| private int | numberOfUsersOfTypeLocked(int flags, boolean excludeDying)
int count = 0;
for (int i = mUsers.size() - 1; i >= 0; i--) {
UserInfo user = mUsers.valueAt(i);
if (!excludeDying || !mRemovingUserIds.get(user.id)) {
if ((user.flags & flags) != 0) {
count++;
}
}
}
return count;
| private java.lang.String | packageToRestrictionsFileName(java.lang.String packageName)
return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
| private java.lang.String | passwordToHash(java.lang.String password, long salt)
if (password == null) {
return null;
}
String algo = null;
String hashed = salt + password;
try {
byte[] saltedPassword = (password + salt).getBytes();
byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
hashed = toHex(sha1) + toHex(md5);
} catch (NoSuchAlgorithmException e) {
Log.w(LOG_TAG, "Failed to encode string because of missing algorithm: " + algo);
}
return hashed;
| private android.os.Bundle | readApplicationRestrictionsLocked(java.lang.String packageName, int userId)
final Bundle restrictions = new Bundle();
final ArrayList<String> values = new ArrayList<String>();
FileInputStream fis = null;
try {
AtomicFile restrictionsFile =
new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
packageToRestrictionsFileName(packageName)));
fis = restrictionsFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
;
}
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read restrictions file "
+ restrictionsFile.getBaseFile());
return restrictions;
}
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_ENTRY)) {
String key = parser.getAttributeValue(null, ATTR_KEY);
String valType = parser.getAttributeValue(null, ATTR_VALUE_TYPE);
String multiple = parser.getAttributeValue(null, ATTR_MULTIPLE);
if (multiple != null) {
values.clear();
int count = Integer.parseInt(multiple);
while (count > 0 && (type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG
&& parser.getName().equals(TAG_VALUE)) {
values.add(parser.nextText().trim());
count--;
}
}
String [] valueStrings = new String[values.size()];
values.toArray(valueStrings);
restrictions.putStringArray(key, valueStrings);
} else {
String value = parser.nextText().trim();
if (ATTR_TYPE_BOOLEAN.equals(valType)) {
restrictions.putBoolean(key, Boolean.parseBoolean(value));
} else if (ATTR_TYPE_INTEGER.equals(valType)) {
restrictions.putInt(key, Integer.parseInt(value));
} else {
restrictions.putString(key, value);
}
}
}
}
} catch (IOException ioe) {
} catch (XmlPullParserException pe) {
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
return restrictions;
| private void | readBoolean(org.xmlpull.v1.XmlPullParser parser, android.os.Bundle restrictions, java.lang.String restrictionKey)
String value = parser.getAttributeValue(null, restrictionKey);
if (value != null) {
restrictions.putBoolean(restrictionKey, Boolean.parseBoolean(value));
}
| private int | readIntAttribute(org.xmlpull.v1.XmlPullParser parser, java.lang.String attr, int defaultValue)
String valueString = parser.getAttributeValue(null, attr);
if (valueString == null) return defaultValue;
try {
return Integer.parseInt(valueString);
} catch (NumberFormatException nfe) {
return defaultValue;
}
| private long | readLongAttribute(org.xmlpull.v1.XmlPullParser parser, java.lang.String attr, long defaultValue)
String valueString = parser.getAttributeValue(null, attr);
if (valueString == null) return defaultValue;
try {
return Long.parseLong(valueString);
} catch (NumberFormatException nfe) {
return defaultValue;
}
| private void | readRestrictionsLocked(org.xmlpull.v1.XmlPullParser parser, android.os.Bundle restrictions)
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_WIFI);
readBoolean(parser, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS);
readBoolean(parser, restrictions, UserManager.DISALLOW_INSTALL_APPS);
readBoolean(parser, restrictions, UserManager.DISALLOW_UNINSTALL_APPS);
readBoolean(parser, restrictions, UserManager.DISALLOW_SHARE_LOCATION);
readBoolean(parser, restrictions,
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH);
readBoolean(parser, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CREDENTIALS);
readBoolean(parser, restrictions, UserManager.DISALLOW_REMOVE_USER);
readBoolean(parser, restrictions, UserManager.DISALLOW_DEBUGGING_FEATURES);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_VPN);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_TETHERING);
readBoolean(parser, restrictions, UserManager.DISALLOW_FACTORY_RESET);
readBoolean(parser, restrictions, UserManager.DISALLOW_ADD_USER);
readBoolean(parser, restrictions, UserManager.ENSURE_VERIFY_APPS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
readBoolean(parser, restrictions, UserManager.DISALLOW_APPS_CONTROL);
readBoolean(parser, restrictions,
UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
readBoolean(parser, restrictions, UserManager.DISALLOW_SMS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
| private void | readUserListLocked()
if (!mUserListFile.exists()) {
fallbackToSingleUserLocked();
return;
}
FileInputStream fis = null;
AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
fis = userListFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
;
}
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read user list");
fallbackToSingleUserLocked();
return;
}
mNextSerialNumber = -1;
if (parser.getName().equals(TAG_USERS)) {
String lastSerialNumber = parser.getAttributeValue(null, ATTR_NEXT_SERIAL_NO);
if (lastSerialNumber != null) {
mNextSerialNumber = Integer.parseInt(lastSerialNumber);
}
String versionNumber = parser.getAttributeValue(null, ATTR_USER_VERSION);
if (versionNumber != null) {
mUserVersion = Integer.parseInt(versionNumber);
}
}
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG) {
final String name = parser.getName();
if (name.equals(TAG_USER)) {
String id = parser.getAttributeValue(null, ATTR_ID);
UserInfo user = readUserLocked(Integer.parseInt(id));
if (user != null) {
mUsers.put(user.id, user);
if (mNextSerialNumber < 0 || mNextSerialNumber <= user.id) {
mNextSerialNumber = user.id + 1;
}
}
} else if (name.equals(TAG_GUEST_RESTRICTIONS)) {
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.END_TAG) {
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals(TAG_RESTRICTIONS)) {
readRestrictionsLocked(parser, mGuestRestrictions);
}
break;
}
}
}
}
}
updateUserIdsLocked();
upgradeIfNecessaryLocked();
} catch (IOException ioe) {
fallbackToSingleUserLocked();
} catch (XmlPullParserException pe) {
fallbackToSingleUserLocked();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
| private android.content.pm.UserInfo | readUserLocked(int id)
int flags = 0;
int serialNumber = id;
String name = null;
String iconPath = null;
long creationTime = 0L;
long lastLoggedInTime = 0L;
long salt = 0L;
String pinHash = null;
int failedAttempts = 0;
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
long lastAttemptTime = 0L;
boolean partial = false;
boolean guestToRemove = false;
Bundle restrictions = new Bundle();
FileInputStream fis = null;
try {
AtomicFile userFile =
new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
fis = userFile.openRead();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(fis, null);
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
;
}
if (type != XmlPullParser.START_TAG) {
Slog.e(LOG_TAG, "Unable to read user " + id);
return null;
}
if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
int storedId = readIntAttribute(parser, ATTR_ID, -1);
if (storedId != id) {
Slog.e(LOG_TAG, "User id does not match the file name");
return null;
}
serialNumber = readIntAttribute(parser, ATTR_SERIAL_NO, id);
flags = readIntAttribute(parser, ATTR_FLAGS, 0);
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
salt = readLongAttribute(parser, ATTR_SALT, 0L);
pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
UserInfo.NO_PROFILE_GROUP_ID);
if (profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
// This attribute was added and renamed during development of L.
// TODO Remove upgrade path by 1st May 2014
profileGroupId = readIntAttribute(parser, "relatedGroupId",
UserInfo.NO_PROFILE_GROUP_ID);
}
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
if ("true".equals(valueString)) {
partial = true;
}
valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
if ("true".equals(valueString)) {
guestToRemove = true;
}
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tag = parser.getName();
if (TAG_NAME.equals(tag)) {
type = parser.next();
if (type == XmlPullParser.TEXT) {
name = parser.getText();
}
} else if (TAG_RESTRICTIONS.equals(tag)) {
readRestrictionsLocked(parser, restrictions);
}
}
}
UserInfo userInfo = new UserInfo(id, name, iconPath, flags);
userInfo.serialNumber = serialNumber;
userInfo.creationTime = creationTime;
userInfo.lastLoggedInTime = lastLoggedInTime;
userInfo.partial = partial;
userInfo.guestToRemove = guestToRemove;
userInfo.profileGroupId = profileGroupId;
mUserRestrictions.append(id, restrictions);
if (salt != 0L) {
RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
if (pinState == null) {
pinState = new RestrictionsPinState();
mRestrictionsPinStates.put(id, pinState);
}
pinState.salt = salt;
pinState.pinHash = pinHash;
pinState.failedAttempts = failedAttempts;
pinState.lastAttemptTime = lastAttemptTime;
}
return userInfo;
} catch (IOException ioe) {
} catch (XmlPullParserException pe) {
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
}
}
}
return null;
| private void | removeDirectoryRecursive(java.io.File parent)
if (parent.isDirectory()) {
String[] files = parent.list();
for (String filename : files) {
File child = new File(parent, filename);
removeDirectoryRecursive(child);
}
}
parent.delete();
| public void | removeRestrictions()
checkManageUsersPermission("Only system can remove restrictions");
final int userHandle = UserHandle.getCallingUserId();
removeRestrictionsForUser(userHandle, true);
| private void | removeRestrictionsForUser(int userHandle, boolean unhideApps)
synchronized (mPackagesLock) {
// Remove all user restrictions
setUserRestrictions(new Bundle(), userHandle);
// Remove restrictions pin
setRestrictionsChallenge(null);
// Remove any app restrictions
cleanAppRestrictions(userHandle);
}
if (unhideApps) {
unhideAllInstalledAppsForUser(userHandle);
}
| public boolean | removeUser(int userHandle)Removes a user and all data directories created for that user. This method should be called
after the user's processes have been terminated.
checkManageUsersPermission("Only the system can remove users");
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
UserManager.DISALLOW_REMOVE_USER, false)) {
Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
return false;
}
long ident = Binder.clearCallingIdentity();
try {
final UserInfo user;
synchronized (mPackagesLock) {
user = mUsers.get(userHandle);
if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
return false;
}
// We remember deleted user IDs to prevent them from being
// reused during the current boot; they can still be reused
// after a reboot.
mRemovingUserIds.put(userHandle, true);
try {
mAppOpsService.removeUser(userHandle);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e);
}
// Set this to a partially created user, so that the user will be purged
// on next startup, in case the runtime stops now before stopping and
// removing the user completely.
user.partial = true;
// Mark it as disabled, so that it isn't returned any more when
// profiles are queried.
user.flags |= UserInfo.FLAG_DISABLED;
writeUserLocked(user);
}
if (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
&& user.isManagedProfile()) {
// Send broadcast to notify system that the user removed was a
// managed user.
sendProfileRemovedBroadcast(user.profileGroupId, user.id);
}
if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
int res;
try {
res = ActivityManagerNative.getDefault().stopUser(userHandle,
new IStopUserCallback.Stub() {
@Override
public void userStopped(int userId) {
finishRemoveUser(userId);
}
@Override
public void userStopAborted(int userId) {
}
});
} catch (RemoteException e) {
return false;
}
return res == ActivityManager.USER_OP_SUCCESS;
} finally {
Binder.restoreCallingIdentity(ident);
}
| private void | removeUserStateLocked(int userHandle)
// Cleanup package manager settings
mPm.cleanUpUserLILPw(this, userHandle);
// Remove this user from the list
mUsers.remove(userHandle);
mRestrictionsPinStates.remove(userHandle);
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
userFile.delete();
// Update the user list
writeUserListLocked();
updateUserIdsLocked();
removeDirectoryRecursive(Environment.getUserSystemDirectory(userHandle));
| private java.lang.String | restrictionsFileNameToPackage(java.lang.String fileName)
return fileName.substring(RESTRICTIONS_FILE_PREFIX.length(),
(int) (fileName.length() - XML_SUFFIX.length()));
| private void | sendProfileRemovedBroadcast(int parentUserId, int removedUserId)
Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
managedProfileIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
Intent.FLAG_RECEIVER_FOREGROUND);
managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(removedUserId));
mContext.sendBroadcastAsUser(managedProfileIntent, new UserHandle(parentUserId), null);
| private void | sendUserInfoChangedBroadcast(int userId)
Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED);
changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(changedIntent, UserHandle.ALL);
| public void | setApplicationRestrictions(java.lang.String packageName, android.os.Bundle restrictions, int userId)
if (UserHandle.getCallingUserId() != userId
|| !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
checkManageUsersPermission("Only system can set restrictions for other users/apps");
}
synchronized (mPackagesLock) {
if (restrictions == null || restrictions.isEmpty()) {
cleanAppRestrictionsForPackage(packageName, userId);
} else {
// Write the restrictions to XML
writeApplicationRestrictionsLocked(packageName, restrictions, userId);
}
}
if (isPackageInstalled(packageName, userId)) {
// Notify package of changes via an intent - only sent to explicitly registered receivers.
Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
changeIntent.setPackage(packageName);
changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(changeIntent, new UserHandle(userId));
}
| public void | setDefaultGuestRestrictions(android.os.Bundle restrictions)
checkManageUsersPermission("setDefaultGuestRestrictions");
synchronized (mPackagesLock) {
mGuestRestrictions.clear();
mGuestRestrictions.putAll(restrictions);
writeUserListLocked();
}
| public boolean | setRestrictionsChallenge(java.lang.String newPin)
checkManageUsersPermission("Only system can modify the restrictions pin");
int userId = UserHandle.getCallingUserId();
synchronized (mPackagesLock) {
RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
if (pinState == null) {
pinState = new RestrictionsPinState();
}
if (newPin == null) {
pinState.salt = 0;
pinState.pinHash = null;
} else {
try {
pinState.salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
} catch (NoSuchAlgorithmException e) {
pinState.salt = (long) (Math.random() * Long.MAX_VALUE);
}
pinState.pinHash = passwordToHash(newPin, pinState.salt);
pinState.failedAttempts = 0;
}
mRestrictionsPinStates.put(userId, pinState);
writeUserLocked(mUsers.get(userId));
}
return true;
| public void | setUserEnabled(int userId)
checkManageUsersPermission("enable user");
synchronized (mPackagesLock) {
UserInfo info = getUserInfoLocked(userId);
if (info != null && !info.isEnabled()) {
info.flags ^= UserInfo.FLAG_DISABLED;
writeUserLocked(info);
}
}
| public void | setUserIcon(int userId, android.graphics.Bitmap bitmap)
checkManageUsersPermission("update users");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "setUserIcon: unknown user #" + userId);
return;
}
writeBitmapLocked(info, bitmap);
writeUserLocked(info);
}
sendUserInfoChangedBroadcast(userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
| public void | setUserName(int userId, java.lang.String name)
checkManageUsersPermission("rename users");
boolean changed = false;
synchronized (mPackagesLock) {
UserInfo info = mUsers.get(userId);
if (info == null || info.partial) {
Slog.w(LOG_TAG, "setUserName: unknown user #" + userId);
return;
}
if (name != null && !name.equals(info.name)) {
info.name = name;
writeUserLocked(info);
changed = true;
}
}
if (changed) {
sendUserInfoChangedBroadcast(userId);
}
| public void | setUserRestrictions(android.os.Bundle restrictions, int userId)
checkManageUsersPermission("setUserRestrictions");
if (restrictions == null) return;
synchronized (mPackagesLock) {
mUserRestrictions.get(userId).clear();
mUserRestrictions.get(userId).putAll(restrictions);
long token = Binder.clearCallingIdentity();
try {
mAppOpsService.setUserRestrictions(mUserRestrictions.get(userId), userId);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
} finally {
Binder.restoreCallingIdentity(token);
}
writeUserLocked(mUsers.get(userId));
}
| void | systemReady()
userForeground(UserHandle.USER_OWNER);
mAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
for (int i = 0; i < mUserIds.length; ++i) {
try {
mAppOpsService.setUserRestrictions(mUserRestrictions.get(mUserIds[i]), mUserIds[i]);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions");
}
}
| private static java.lang.String | toHex(byte[] ary)
final String hex = "0123456789ABCDEF";
String ret = "";
for (int i = 0; i < ary.length; i++) {
ret += hex.charAt((ary[i] >> 4) & 0xf);
ret += hex.charAt(ary[i] & 0xf);
}
return ret;
| private void | unhideAllInstalledAppsForUser(int userHandle)
mHandler.post(new Runnable() {
@Override
public void run() {
List<ApplicationInfo> apps =
mPm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES,
userHandle).getList();
final long ident = Binder.clearCallingIdentity();
try {
for (ApplicationInfo appInfo : apps) {
if ((appInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0
&& (appInfo.flags & ApplicationInfo.FLAG_HIDDEN) != 0) {
mPm.setApplicationHiddenSettingAsUser(appInfo.packageName, false,
userHandle);
}
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
});
| private void | updateUserIdsLocked()Caches the list of user ids in an array, adjusting the array size when necessary.
int num = 0;
for (int i = 0; i < mUsers.size(); i++) {
if (!mUsers.valueAt(i).partial) {
num++;
}
}
final int[] newUsers = new int[num];
int n = 0;
for (int i = 0; i < mUsers.size(); i++) {
if (!mUsers.valueAt(i).partial) {
newUsers[n++] = mUsers.keyAt(i);
}
}
mUserIds = newUsers;
| private void | upgradeIfNecessaryLocked()Upgrade steps between versions, either for fixing bugs or changing the data format.
int userVersion = mUserVersion;
if (userVersion < 1) {
// Assign a proper name for the owner, if not initialized correctly before
UserInfo user = mUsers.get(UserHandle.USER_OWNER);
if ("Primary".equals(user.name)) {
user.name = mContext.getResources().getString(com.android.internal.R.string.owner_name);
writeUserLocked(user);
}
userVersion = 1;
}
if (userVersion < 2) {
// Owner should be marked as initialized
UserInfo user = mUsers.get(UserHandle.USER_OWNER);
if ((user.flags & UserInfo.FLAG_INITIALIZED) == 0) {
user.flags |= UserInfo.FLAG_INITIALIZED;
writeUserLocked(user);
}
userVersion = 2;
}
if (userVersion < 4) {
userVersion = 4;
}
if (userVersion < 5) {
initDefaultGuestRestrictions();
userVersion = 5;
}
if (userVersion < USER_VERSION) {
Slog.w(LOG_TAG, "User version " + mUserVersion + " didn't upgrade as expected to "
+ USER_VERSION);
} else {
mUserVersion = userVersion;
writeUserListLocked();
}
| public void | userForeground(int userId)Make a note of the last started time of a user and do some cleanup.
synchronized (mPackagesLock) {
UserInfo user = mUsers.get(userId);
long now = System.currentTimeMillis();
if (user == null || user.partial) {
Slog.w(LOG_TAG, "userForeground: unknown user #" + userId);
return;
}
if (now > EPOCH_PLUS_30_YEARS) {
user.lastLoggedInTime = now;
writeUserLocked(user);
}
}
| private void | writeApplicationRestrictionsLocked(java.lang.String packageName, android.os.Bundle restrictions, int userId)
FileOutputStream fos = null;
AtomicFile restrictionsFile = new AtomicFile(
new File(Environment.getUserSystemDirectory(userId),
packageToRestrictionsFileName(packageName)));
try {
fos = restrictionsFile.startWrite();
final BufferedOutputStream bos = new BufferedOutputStream(fos);
// XmlSerializer serializer = XmlUtils.serializerInstance();
final XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(bos, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, TAG_RESTRICTIONS);
for (String key : restrictions.keySet()) {
Object value = restrictions.get(key);
serializer.startTag(null, TAG_ENTRY);
serializer.attribute(null, ATTR_KEY, key);
if (value instanceof Boolean) {
serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_BOOLEAN);
serializer.text(value.toString());
} else if (value instanceof Integer) {
serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_INTEGER);
serializer.text(value.toString());
} else if (value == null || value instanceof String) {
serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING);
serializer.text(value != null ? (String) value : "");
} else {
serializer.attribute(null, ATTR_VALUE_TYPE, ATTR_TYPE_STRING_ARRAY);
String[] values = (String[]) value;
serializer.attribute(null, ATTR_MULTIPLE, Integer.toString(values.length));
for (String choice : values) {
serializer.startTag(null, TAG_VALUE);
serializer.text(choice != null ? choice : "");
serializer.endTag(null, TAG_VALUE);
}
}
serializer.endTag(null, TAG_ENTRY);
}
serializer.endTag(null, TAG_RESTRICTIONS);
serializer.endDocument();
restrictionsFile.finishWrite(fos);
} catch (Exception e) {
restrictionsFile.failWrite(fos);
Slog.e(LOG_TAG, "Error writing application restrictions list");
}
| private void | writeBitmapLocked(android.content.pm.UserInfo info, android.graphics.Bitmap bitmap)
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
File file = new File(dir, USER_PHOTO_FILENAME);
if (!dir.exists()) {
dir.mkdir();
FileUtils.setPermissions(
dir.getPath(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-1, -1);
}
FileOutputStream os;
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, os = new FileOutputStream(file))) {
info.iconPath = file.getAbsolutePath();
}
try {
os.close();
} catch (IOException ioe) {
// What the ... !
}
} catch (FileNotFoundException e) {
Slog.w(LOG_TAG, "Error setting photo for user ", e);
}
| private void | writeBoolean(org.xmlpull.v1.XmlSerializer xml, android.os.Bundle restrictions, java.lang.String restrictionKey)
if (restrictions.containsKey(restrictionKey)) {
xml.attribute(null, restrictionKey,
Boolean.toString(restrictions.getBoolean(restrictionKey)));
}
| private void | writeRestrictionsLocked(org.xmlpull.v1.XmlSerializer serializer, android.os.Bundle restrictions)
serializer.startTag(null, TAG_RESTRICTIONS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_WIFI);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_MODIFY_ACCOUNTS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_INSTALL_APPS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNINSTALL_APPS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_SHARE_LOCATION);
writeBoolean(serializer, restrictions,
UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CREDENTIALS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_REMOVE_USER);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_DEBUGGING_FEATURES);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_VPN);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_TETHERING);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_FACTORY_RESET);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADD_USER);
writeBoolean(serializer, restrictions, UserManager.ENSURE_VERIFY_APPS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_APPS_CONTROL);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
serializer.endTag(null, TAG_RESTRICTIONS);
| private void | writeUserListLocked()
FileOutputStream fos = null;
AtomicFile userListFile = new AtomicFile(mUserListFile);
try {
fos = userListFile.startWrite();
final BufferedOutputStream bos = new BufferedOutputStream(fos);
// XmlSerializer serializer = XmlUtils.serializerInstance();
final XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(bos, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, TAG_USERS);
serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
writeRestrictionsLocked(serializer, mGuestRestrictions);
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
for (int i = 0; i < mUsers.size(); i++) {
UserInfo user = mUsers.valueAt(i);
serializer.startTag(null, TAG_USER);
serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
serializer.endTag(null, TAG_USER);
}
serializer.endTag(null, TAG_USERS);
serializer.endDocument();
userListFile.finishWrite(fos);
} catch (Exception e) {
userListFile.failWrite(fos);
Slog.e(LOG_TAG, "Error writing user list");
}
| private void | writeUserLocked(android.content.pm.UserInfo userInfo)
FileOutputStream fos = null;
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + XML_SUFFIX));
try {
fos = userFile.startWrite();
final BufferedOutputStream bos = new BufferedOutputStream(fos);
// XmlSerializer serializer = XmlUtils.serializerInstance();
final XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(bos, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, TAG_USER);
serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
serializer.attribute(null, ATTR_SERIAL_NO, Integer.toString(userInfo.serialNumber));
serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
Long.toString(userInfo.lastLoggedInTime));
RestrictionsPinState pinState = mRestrictionsPinStates.get(userInfo.id);
if (pinState != null) {
if (pinState.salt != 0) {
serializer.attribute(null, ATTR_SALT, Long.toString(pinState.salt));
}
if (pinState.pinHash != null) {
serializer.attribute(null, ATTR_PIN_HASH, pinState.pinHash);
}
if (pinState.failedAttempts != 0) {
serializer.attribute(null, ATTR_FAILED_ATTEMPTS,
Integer.toString(pinState.failedAttempts));
serializer.attribute(null, ATTR_LAST_RETRY_MS,
Long.toString(pinState.lastAttemptTime));
}
}
if (userInfo.iconPath != null) {
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
}
if (userInfo.partial) {
serializer.attribute(null, ATTR_PARTIAL, "true");
}
if (userInfo.guestToRemove) {
serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
}
if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
Integer.toString(userInfo.profileGroupId));
}
serializer.startTag(null, TAG_NAME);
serializer.text(userInfo.name);
serializer.endTag(null, TAG_NAME);
Bundle restrictions = mUserRestrictions.get(userInfo.id);
if (restrictions != null) {
writeRestrictionsLocked(serializer, restrictions);
}
serializer.endTag(null, TAG_USER);
serializer.endDocument();
userFile.finishWrite(fos);
} catch (Exception ioe) {
Slog.e(LOG_TAG, "Error writing user info " + userInfo.id + "\n" + ioe);
userFile.failWrite(fos);
}
|
|