summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2012-09-18 15:48:21 -0700
committerDianne Hackborn <hackbod@google.com>2012-09-18 18:20:43 -0700
commitbb1aeff3202a51b1db020be272178f50a2f2502d (patch)
treebb9826d6629cf4607fa46e3b9c049aafb07d9ffc /services
parentc535d2f30efff83b93094bbc642d59d8225dcc18 (diff)
downloadframeworks_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.java117
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.