Loading services/java/com/android/server/pm/UserManagerService.java +42 −23 Original line number Diff line number Diff line Loading @@ -16,8 +16,7 @@ package com.android.server.pm; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import android.app.Activity; import android.app.ActivityManager; Loading @@ -26,7 +25,6 @@ import android.app.IStopUserCallback; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.graphics.Bitmap; Loading @@ -34,6 +32,7 @@ import android.graphics.BitmapFactory; import android.os.Binder; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; import android.os.IUserManager; import android.os.Process; import android.os.RemoteException; Loading @@ -42,9 +41,17 @@ import android.os.UserManager; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.TimeUtils; import android.util.Xml; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileDescriptor; Loading @@ -54,13 +61,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; public class UserManagerService extends IUserManager.Stub { private static final String LOG_TAG = "UserManagerService"; Loading Loading @@ -95,19 +97,24 @@ public class UserManagerService extends IUserManager.Stub { private final Object mInstallLock; private final Object mPackagesLock; private final Handler mHandler; private final File mUsersDir; private final File mUserListFile; private final File mBaseUserPath; private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); private HashSet<Integer> mRemovingUserIds = new HashSet<Integer>(); private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); /** * Set of user IDs being actively removed. Removed IDs linger in this set * for several seconds to work around a VFS caching issue. */ // @GuardedBy("mPackagesLock") private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray(); private int[] mUserIds; private boolean mGuestEnabled; private int mNextSerialNumber; // This resets on a reboot. Otherwise it keeps incrementing so that user ids are // not reused in quick succession private int mNextUserId = MIN_USER_ID; private int mUserVersion = 0; private static UserManagerService sInstance; Loading Loading @@ -147,6 +154,7 @@ public class UserManagerService extends IUserManager.Stub { mPm = pm; mInstallLock = installLock; mPackagesLock = packagesLock; mHandler = new Handler(); synchronized (mInstallLock) { synchronized (mPackagesLock) { mUsersDir = new File(dataDir, USER_INFO_DIR); Loading Loading @@ -190,7 +198,7 @@ public class UserManagerService extends IUserManager.Stub { if (ui.partial) { continue; } if (!excludeDying || !mRemovingUserIds.contains(ui.id)) { if (!excludeDying || !mRemovingUserIds.get(ui.id)) { users.add(ui); } } Loading @@ -212,7 +220,7 @@ public class UserManagerService extends IUserManager.Stub { private 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.contains(userId)) { if (ui != null && ui.partial && !mRemovingUserIds.get(userId)) { Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId); return null; } Loading Loading @@ -749,7 +757,7 @@ public class UserManagerService extends IUserManager.Stub { if (userHandle == 0 || user == null) { return false; } mRemovingUserIds.add(userHandle); mRemovingUserIds.put(userHandle, true); // 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. Loading Loading @@ -813,13 +821,25 @@ public class UserManagerService extends IUserManager.Stub { } } private void removeUserStateLocked(int userHandle) { private void removeUserStateLocked(final int userHandle) { // Cleanup package manager settings mPm.cleanUpUserLILPw(userHandle); // Remove this user from the list mUsers.remove(userHandle); mRemovingUserIds.remove(userHandle); // Have user ID linger for several seconds to let external storage VFS // cache entries expire. This must be greater than the 'entry_valid' // timeout used by the FUSE daemon. mHandler.postDelayed(new Runnable() { @Override public void run() { synchronized (mPackagesLock) { mRemovingUserIds.delete(userHandle); } } }, MINUTE_IN_MILLIS); // Remove user file AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml")); userFile.delete(); Loading Loading @@ -906,14 +926,13 @@ public class UserManagerService extends IUserManager.Stub { */ private int getNextAvailableIdLocked() { synchronized (mPackagesLock) { int i = mNextUserId; int i = MIN_USER_ID; while (i < Integer.MAX_VALUE) { if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.contains(i)) { if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) { break; } i++; } mNextUserId = i + 1; return i; } } Loading @@ -938,7 +957,7 @@ public class UserManagerService extends IUserManager.Stub { UserInfo user = mUsers.valueAt(i); if (user == null) continue; pw.print(" "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber); if (mRemovingUserIds.contains(mUsers.keyAt(i))) pw.print(" <removing> "); if (mRemovingUserIds.get(mUsers.keyAt(i))) pw.print(" <removing> "); if (user.partial) pw.print(" <partial>"); pw.println(); pw.print(" Created: "); Loading Loading
services/java/com/android/server/pm/UserManagerService.java +42 −23 Original line number Diff line number Diff line Loading @@ -16,8 +16,7 @@ package com.android.server.pm; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import android.app.Activity; import android.app.ActivityManager; Loading @@ -26,7 +25,6 @@ import android.app.IStopUserCallback; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.graphics.Bitmap; Loading @@ -34,6 +32,7 @@ import android.graphics.BitmapFactory; import android.os.Binder; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; import android.os.IUserManager; import android.os.Process; import android.os.RemoteException; Loading @@ -42,9 +41,17 @@ import android.os.UserManager; import android.util.AtomicFile; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.TimeUtils; import android.util.Xml; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileDescriptor; Loading @@ -54,13 +61,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; public class UserManagerService extends IUserManager.Stub { private static final String LOG_TAG = "UserManagerService"; Loading Loading @@ -95,19 +97,24 @@ public class UserManagerService extends IUserManager.Stub { private final Object mInstallLock; private final Object mPackagesLock; private final Handler mHandler; private final File mUsersDir; private final File mUserListFile; private final File mBaseUserPath; private SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); private HashSet<Integer> mRemovingUserIds = new HashSet<Integer>(); private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>(); /** * Set of user IDs being actively removed. Removed IDs linger in this set * for several seconds to work around a VFS caching issue. */ // @GuardedBy("mPackagesLock") private final SparseBooleanArray mRemovingUserIds = new SparseBooleanArray(); private int[] mUserIds; private boolean mGuestEnabled; private int mNextSerialNumber; // This resets on a reboot. Otherwise it keeps incrementing so that user ids are // not reused in quick succession private int mNextUserId = MIN_USER_ID; private int mUserVersion = 0; private static UserManagerService sInstance; Loading Loading @@ -147,6 +154,7 @@ public class UserManagerService extends IUserManager.Stub { mPm = pm; mInstallLock = installLock; mPackagesLock = packagesLock; mHandler = new Handler(); synchronized (mInstallLock) { synchronized (mPackagesLock) { mUsersDir = new File(dataDir, USER_INFO_DIR); Loading Loading @@ -190,7 +198,7 @@ public class UserManagerService extends IUserManager.Stub { if (ui.partial) { continue; } if (!excludeDying || !mRemovingUserIds.contains(ui.id)) { if (!excludeDying || !mRemovingUserIds.get(ui.id)) { users.add(ui); } } Loading @@ -212,7 +220,7 @@ public class UserManagerService extends IUserManager.Stub { private 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.contains(userId)) { if (ui != null && ui.partial && !mRemovingUserIds.get(userId)) { Slog.w(LOG_TAG, "getUserInfo: unknown user #" + userId); return null; } Loading Loading @@ -749,7 +757,7 @@ public class UserManagerService extends IUserManager.Stub { if (userHandle == 0 || user == null) { return false; } mRemovingUserIds.add(userHandle); mRemovingUserIds.put(userHandle, true); // 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. Loading Loading @@ -813,13 +821,25 @@ public class UserManagerService extends IUserManager.Stub { } } private void removeUserStateLocked(int userHandle) { private void removeUserStateLocked(final int userHandle) { // Cleanup package manager settings mPm.cleanUpUserLILPw(userHandle); // Remove this user from the list mUsers.remove(userHandle); mRemovingUserIds.remove(userHandle); // Have user ID linger for several seconds to let external storage VFS // cache entries expire. This must be greater than the 'entry_valid' // timeout used by the FUSE daemon. mHandler.postDelayed(new Runnable() { @Override public void run() { synchronized (mPackagesLock) { mRemovingUserIds.delete(userHandle); } } }, MINUTE_IN_MILLIS); // Remove user file AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml")); userFile.delete(); Loading Loading @@ -906,14 +926,13 @@ public class UserManagerService extends IUserManager.Stub { */ private int getNextAvailableIdLocked() { synchronized (mPackagesLock) { int i = mNextUserId; int i = MIN_USER_ID; while (i < Integer.MAX_VALUE) { if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.contains(i)) { if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) { break; } i++; } mNextUserId = i + 1; return i; } } Loading @@ -938,7 +957,7 @@ public class UserManagerService extends IUserManager.Stub { UserInfo user = mUsers.valueAt(i); if (user == null) continue; pw.print(" "); pw.print(user); pw.print(" serialNo="); pw.print(user.serialNumber); if (mRemovingUserIds.contains(mUsers.keyAt(i))) pw.print(" <removing> "); if (mRemovingUserIds.get(mUsers.keyAt(i))) pw.print(" <removing> "); if (user.partial) pw.print(" <partial>"); pw.println(); pw.print(" Created: "); Loading