Skip to content

Commit bb1aeff

Browse files
author
Dianne Hackborn
committed
Don't allow more than 3 actively running users at a time.
Change-Id: Ic047c62b518a0faaa7b507343909330044ec290b
1 parent c535d2f commit bb1aeff

File tree

1 file changed

+76
-41
lines changed

1 file changed

+76
-41
lines changed

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 76 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)