@@ -253,6 +253,9 @@ public final class ActivityManagerService extends ActivityManagerNative
253253 // giving up on them and unfreezing the screen.
254254 static final int USER_SWITCH_TIMEOUT = 2*1000;
255255
256+ // Maximum number of users we allow to be running at a time.
257+ static final int MAX_RUNNING_USERS = 3;
258+
256259 static final int MY_PID = Process.myPid();
257260
258261 static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -14123,6 +14126,33 @@ void finishUserSwitch(UserStartedState uss) {
1412314126 android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
1412414127 false, false, MY_PID, Process.SYSTEM_UID, userId);
1412514128 }
14129+ int num = mUserLru.size();
14130+ int i = 0;
14131+ while (num > MAX_RUNNING_USERS && i < mUserLru.size()) {
14132+ Integer oldUserId = mUserLru.get(i);
14133+ UserStartedState oldUss = mStartedUsers.get(oldUserId);
14134+ if (oldUss == null) {
14135+ // Shouldn't happen, but be sane if it does.
14136+ mUserLru.remove(i);
14137+ num--;
14138+ continue;
14139+ }
14140+ if (oldUss.mState == UserStartedState.STATE_STOPPING) {
14141+ // This user is already stopping, doesn't count.
14142+ num--;
14143+ i++;
14144+ continue;
14145+ }
14146+ if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId) {
14147+ // Owner and current can't be stopped, but count as running.
14148+ i++;
14149+ continue;
14150+ }
14151+ // This is a user to be stopped.
14152+ stopUserLocked(oldUserId, null);
14153+ num--;
14154+ i++;
14155+ }
1412614156 }
1412714157 }
1412814158
@@ -14141,52 +14171,56 @@ public int stopUser(final int userId, final IStopUserCallback callback) {
1414114171 throw new IllegalArgumentException("Can't stop primary user " + userId);
1414214172 }
1414314173 synchronized (this) {
14144- if (mCurrentUserId == userId) {
14145- return ActivityManager.USER_OP_IS_CURRENT;
14146- }
14147-
14148- final UserStartedState uss = mStartedUsers.get(userId);
14149- if (uss == null) {
14150- // User is not started, nothing to do... but we do need to
14151- // callback if requested.
14152- if (callback != null) {
14153- mHandler.post(new Runnable() {
14154- @Override
14155- public void run() {
14156- try {
14157- callback.userStopped(userId);
14158- } catch (RemoteException e) {
14159- }
14160- }
14161- });
14162- }
14163- return ActivityManager.USER_OP_SUCCESS;
14164- }
14174+ return stopUserLocked(userId, callback);
14175+ }
14176+ }
1416514177
14178+ private int stopUserLocked(final int userId, final IStopUserCallback callback) {
14179+ if (mCurrentUserId == userId) {
14180+ return ActivityManager.USER_OP_IS_CURRENT;
14181+ }
14182+
14183+ final UserStartedState uss = mStartedUsers.get(userId);
14184+ if (uss == null) {
14185+ // User is not started, nothing to do... but we do need to
14186+ // callback if requested.
1416614187 if (callback != null) {
14167- uss.mStopCallbacks.add(callback);
14188+ mHandler.post(new Runnable() {
14189+ @Override
14190+ public void run() {
14191+ try {
14192+ callback.userStopped(userId);
14193+ } catch (RemoteException e) {
14194+ }
14195+ }
14196+ });
1416814197 }
14198+ return ActivityManager.USER_OP_SUCCESS;
14199+ }
1416914200
14170- if (uss.mState != UserStartedState.STATE_STOPPING) {
14171- uss.mState = UserStartedState.STATE_STOPPING;
14201+ if (callback != null) {
14202+ uss.mStopCallbacks.add(callback);
14203+ }
1417214204
14173- long ident = Binder.clearCallingIdentity();
14174- try {
14175- // Inform of user switch
14176- Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
14177- final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() {
14178- @Override
14179- public void performReceive(Intent intent, int resultCode, String data,
14180- Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
14181- finishUserStop(uss);
14182- }
14183- };
14184- broadcastIntentLocked(null, null, intent,
14185- null, resultReceiver, 0, null, null, null,
14186- true, false, MY_PID, Process.SYSTEM_UID, userId);
14187- } finally {
14188- Binder.restoreCallingIdentity(ident);
14189- }
14205+ if (uss.mState != UserStartedState.STATE_STOPPING) {
14206+ uss.mState = UserStartedState.STATE_STOPPING;
14207+
14208+ long ident = Binder.clearCallingIdentity();
14209+ try {
14210+ // Inform of user switch
14211+ Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
14212+ final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() {
14213+ @Override
14214+ public void performReceive(Intent intent, int resultCode, String data,
14215+ Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
14216+ finishUserStop(uss);
14217+ }
14218+ };
14219+ broadcastIntentLocked(null, null, intent,
14220+ null, resultReceiver, 0, null, null, null,
14221+ true, false, MY_PID, Process.SYSTEM_UID, userId);
14222+ } finally {
14223+ Binder.restoreCallingIdentity(ident);
1419014224 }
1419114225 }
1419214226
@@ -14206,6 +14240,7 @@ void finishUserStop(UserStartedState uss) {
1420614240 stopped = true;
1420714241 // User can no longer run.
1420814242 mStartedUsers.remove(userId);
14243+ mUserLru.remove(Integer.valueOf(userId));
1420914244
1421014245 // Clean up all state and processes associated with the user.
1421114246 // Kill all the processes for the user.
0 commit comments