diff options
5 files changed, 44 insertions, 8 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 999db18a1229..6151b8e2ef0a 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -142,6 +142,15 @@ public abstract class ActivityManagerInternal { String processName, String abiOverride, int uid, Runnable crashHandler); /** + * Called when a user is being deleted. This can happen during normal device usage + * or just at startup, when partially removed users are purged. Any state persisted by the + * ActivityManager should be purged now. + * + * @param userId The user being cleaned up. + */ + public abstract void onUserRemoving(@UserIdInt int userId); + + /** * Called when a user has been deleted. This can happen during normal device usage * or just at startup, when partially removed users are purged. Any state persisted by the * ActivityManager should be purged now. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5c14c4a2aabe..61d439b2defe 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -16659,7 +16659,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void onUserRemoved(@UserIdInt int userId) { + public void onUserRemoving(@UserIdInt int userId) { // Clean up any ActivityTaskManager state (by telling it the user is stopped) mAtmInternal.onUserStopped(userId); // Clean up various services by removing the user @@ -16673,6 +16673,12 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public void onUserRemoved(int userId) { + // Clean up UserController state + mUserController.onUserRemoved(userId); + } + + @Override public boolean startUserInBackground(final int userId) { return ActivityManagerService.this.startUserInBackground(userId); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 9f302fed626f..d76c04ac7f31 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -445,11 +445,6 @@ class UserController implements Handler.Callback { public void onUserCreated(UserInfo user, Object token) { onUserAdded(user); } - - @Override - public void onUserRemoved(UserInfo user) { - UserController.this.onUserRemoved(user.id); - } }; UserController(ActivityManagerService service) { @@ -3357,10 +3352,12 @@ class UserController implements Handler.Callback { if (mUserProfileGroupIds.keyAt(i) == userId || mUserProfileGroupIds.valueAt(i) == userId) { mUserProfileGroupIds.removeAt(i); - } } mCurrentProfileIds = ArrayUtils.removeInt(mCurrentProfileIds, userId); + mUserLru.remove((Integer) userId); + mStartedUsers.remove(userId); + updateStartedUserArrayLU(); } } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 8249d65868cd..81956fbb55e6 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -6661,7 +6661,7 @@ public class UserManagerService extends IUserManager.Stub { + userId); } new Thread(() -> { - getActivityManagerInternal().onUserRemoved(userId); + getActivityManagerInternal().onUserRemoving(userId); removeUserState(userId); }).start(); } @@ -6701,6 +6701,7 @@ public class UserManagerService extends IUserManager.Stub { synchronized (mUsersLock) { removeUserDataLU(userId); mIsUserManaged.delete(userId); + getActivityManagerInternal().onUserRemoved(userId); } synchronized (mUserStates) { mUserStates.delete(userId); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java index 0bf419ec242c..998c1d1a23b1 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -35,6 +36,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; import android.os.Binder; import android.os.Bundle; import android.os.DropBoxManager; @@ -48,6 +50,7 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; import android.provider.Settings; @@ -68,6 +71,7 @@ import org.junit.Test; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -150,6 +154,25 @@ public class ActivityManagerTest { } @Test + public void testRemovedUserShouldNotBeRunning() throws Exception { + final UserManager userManager = mContext.getSystemService(UserManager.class); + assertNotNull("UserManager should not be null", userManager); + final UserInfo user = userManager.createUser( + "TestUser", UserManager.USER_TYPE_FULL_SECONDARY, 0); + + mService.startUserInBackground(user.id); + assertTrue("User should be running", mService.isUserRunning(user.id, 0)); + assertTrue("User should be in running users", + Arrays.stream(mService.getRunningUserIds()).anyMatch(x -> x == user.id)); + + userManager.removeUser(user.id); + mService.startUserInBackground(user.id); + assertFalse("Removed user should not be running", mService.isUserRunning(user.id, 0)); + assertFalse("Removed user should not be in running users", + Arrays.stream(mService.getRunningUserIds()).anyMatch(x -> x == user.id)); + } + + @Test public void testServiceUnbindAndKilling() { for (int i = TEST_LOOPS; i > 0; i--) { runOnce(i); |