diff options
author | Dianne Hackborn <hackbod@google.com> | 2012-09-18 15:48:21 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2012-09-18 18:20:43 -0700 |
commit | bb1aeff3202a51b1db020be272178f50a2f2502d (patch) | |
tree | bb9826d6629cf4607fa46e3b9c049aafb07d9ffc /services | |
parent | c535d2f30efff83b93094bbc642d59d8225dcc18 (diff) | |
download | frameworks_base-bb1aeff3202a51b1db020be272178f50a2f2502d.zip frameworks_base-bb1aeff3202a51b1db020be272178f50a2f2502d.tar.gz frameworks_base-bb1aeff3202a51b1db020be272178f50a2f2502d.tar.bz2 |
Don't allow more than 3 actively running users at a time.
Change-Id: Ic047c62b518a0faaa7b507343909330044ec290b
Diffstat (limited to 'services')
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 117 |
1 files changed, 76 insertions, 41 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index ce5424b..b77eb59 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -253,6 +253,9 @@ public final class ActivityManagerService extends ActivityManagerNative // giving up on them and unfreezing the screen. static final int USER_SWITCH_TIMEOUT = 2*1000; + // Maximum number of users we allow to be running at a time. + static final int MAX_RUNNING_USERS = 3; + static final int MY_PID = Process.myPid(); static final String[] EMPTY_STRING_ARRAY = new String[0]; @@ -14123,6 +14126,33 @@ public final class ActivityManagerService extends ActivityManagerNative android.Manifest.permission.RECEIVE_BOOT_COMPLETED, false, false, MY_PID, Process.SYSTEM_UID, userId); } + int num = mUserLru.size(); + int i = 0; + while (num > MAX_RUNNING_USERS && i < mUserLru.size()) { + Integer oldUserId = mUserLru.get(i); + UserStartedState oldUss = mStartedUsers.get(oldUserId); + if (oldUss == null) { + // Shouldn't happen, but be sane if it does. + mUserLru.remove(i); + num--; + continue; + } + if (oldUss.mState == UserStartedState.STATE_STOPPING) { + // This user is already stopping, doesn't count. + num--; + i++; + continue; + } + if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId) { + // Owner and current can't be stopped, but count as running. + i++; + continue; + } + // This is a user to be stopped. + stopUserLocked(oldUserId, null); + num--; + i++; + } } } @@ -14141,52 +14171,56 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException("Can't stop primary user " + userId); } synchronized (this) { - if (mCurrentUserId == userId) { - return ActivityManager.USER_OP_IS_CURRENT; - } - - final UserStartedState uss = mStartedUsers.get(userId); - if (uss == null) { - // User is not started, nothing to do... but we do need to - // callback if requested. - if (callback != null) { - mHandler.post(new Runnable() { - @Override - public void run() { - try { - callback.userStopped(userId); - } catch (RemoteException e) { - } - } - }); - } - return ActivityManager.USER_OP_SUCCESS; - } + return stopUserLocked(userId, callback); + } + } + private int stopUserLocked(final int userId, final IStopUserCallback callback) { + if (mCurrentUserId == userId) { + return ActivityManager.USER_OP_IS_CURRENT; + } + + final UserStartedState uss = mStartedUsers.get(userId); + if (uss == null) { + // User is not started, nothing to do... but we do need to + // callback if requested. if (callback != null) { - uss.mStopCallbacks.add(callback); + mHandler.post(new Runnable() { + @Override + public void run() { + try { + callback.userStopped(userId); + } catch (RemoteException e) { + } + } + }); } + return ActivityManager.USER_OP_SUCCESS; + } - if (uss.mState != UserStartedState.STATE_STOPPING) { - uss.mState = UserStartedState.STATE_STOPPING; + if (callback != null) { + uss.mStopCallbacks.add(callback); + } - long ident = Binder.clearCallingIdentity(); - try { - // Inform of user switch - Intent intent = new Intent(Intent.ACTION_SHUTDOWN); - final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() { - @Override - public void performReceive(Intent intent, int resultCode, String data, - Bundle extras, boolean ordered, boolean sticky, int sendingUser) { - finishUserStop(uss); - } - }; - broadcastIntentLocked(null, null, intent, - null, resultReceiver, 0, null, null, null, - true, false, MY_PID, Process.SYSTEM_UID, userId); - } finally { - Binder.restoreCallingIdentity(ident); - } + if (uss.mState != UserStartedState.STATE_STOPPING) { + uss.mState = UserStartedState.STATE_STOPPING; + + long ident = Binder.clearCallingIdentity(); + try { + // Inform of user switch + Intent intent = new Intent(Intent.ACTION_SHUTDOWN); + final IIntentReceiver resultReceiver = new IIntentReceiver.Stub() { + @Override + public void performReceive(Intent intent, int resultCode, String data, + Bundle extras, boolean ordered, boolean sticky, int sendingUser) { + finishUserStop(uss); + } + }; + broadcastIntentLocked(null, null, intent, + null, resultReceiver, 0, null, null, null, + true, false, MY_PID, Process.SYSTEM_UID, userId); + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -14206,6 +14240,7 @@ public final class ActivityManagerService extends ActivityManagerNative stopped = true; // User can no longer run. mStartedUsers.remove(userId); + mUserLru.remove(Integer.valueOf(userId)); // Clean up all state and processes associated with the user. // Kill all the processes for the user. |