Complete the logic around last active user, including: am: f4339b8cb1
am: 69b063d7a7

Change-Id: Idc1180b1ced53f08ee5e396561f980c7d3b8028b
diff --git a/car-lib/src/android/car/user/CarUserManagerHelper.java b/car-lib/src/android/car/user/CarUserManagerHelper.java
index 9aafdff..4105353 100644
--- a/car-lib/src/android/car/user/CarUserManagerHelper.java
+++ b/car-lib/src/android/car/user/CarUserManagerHelper.java
@@ -34,6 +34,7 @@
 import android.provider.Settings;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.UserIcons;
 
 import com.google.android.collect.Sets;
@@ -65,6 +66,7 @@
     private final Context mContext;
     private final UserManager mUserManager;
     private final ActivityManager mActivityManager;
+    private int mLastActiveUser = UserHandle.USER_SYSTEM;
     private Bitmap mDefaultGuestUserIcon;
     private OnUsersUpdateListener mUpdateListener;
     private final BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
@@ -107,7 +109,9 @@
      * Set default boot into user.
      *
      * @param userId default user id to boot into.
+     * @deprecated Setting default user is obsolete
      */
+    @Deprecated
     public void setDefaultBootUser(int userId) {
         Settings.Global.putInt(
                 mContext.getContentResolver(),
@@ -118,17 +122,23 @@
      * Set last active user.
      *
      * @param userId last active user id.
+     * @param skipGlobalSetting whether to skip set the global settings value.
      */
-    public void setLastActiveUser(int userId) {
-        Settings.Global.putInt(
-                mContext.getContentResolver(), CarSettings.Global.LAST_ACTIVE_USER_ID, userId);
+    public void setLastActiveUser(int userId, boolean skipGlobalSetting) {
+        mLastActiveUser = userId;
+        if (!skipGlobalSetting) {
+            Settings.Global.putInt(
+                    mContext.getContentResolver(), CarSettings.Global.LAST_ACTIVE_USER_ID, userId);
+        }
     }
 
     /**
      * Get user id for the default boot into user.
      *
      * @return user id of the default boot into user
+     * @deprecated Use {@link #getLastActiveUser()} instead.
      */
+    @Deprecated
     public int getDefaultBootUser() {
         // Make user 10 the original default boot user.
         return Settings.Global.getInt(
@@ -139,13 +149,46 @@
     /**
      * Get user id for the last active user.
      *
-     * @return user id of the last active user
+     * @return user id of the last active user.
      */
     public int getLastActiveUser() {
-        // Make user 10 the original default last active user.
+        if (mLastActiveUser != UserHandle.USER_SYSTEM) {
+            return mLastActiveUser;
+        }
         return Settings.Global.getInt(
             mContext.getContentResolver(), CarSettings.Global.LAST_ACTIVE_USER_ID,
-            /* default user id= */ 10);
+            /* default user id= */ UserHandle.USER_SYSTEM);
+    }
+
+    /**
+     * Get user id for the initial user to boot into.
+     *
+     * <p>If failed to retrieve the id stored in global settings or the retrieved id does not
+     * exist on device, then return the user with smallest user id.
+     *
+     * @return user id of the last active user or the smallest user id on the device.
+     */
+    public int getInitialUser() {
+        int lastActiveUserId = getLastActiveUser();
+
+        boolean isUserExist = false;
+        List<UserInfo> allUsers = getAllPersistentUsers();
+        int smallestUserId = Integer.MAX_VALUE;
+        for (UserInfo user : allUsers) {
+            if (user.id == lastActiveUserId) {
+                isUserExist = true;
+            }
+            smallestUserId = Math.min(user.id, smallestUserId);
+        }
+
+        // If the last active user is system user or the user id doesn't exist on device,
+        // return the smallest id or all users.
+        if (lastActiveUserId == UserHandle.USER_SYSTEM || !isUserExist) {
+            Log.e(TAG, "Can't get last active user id or the user no longer exist.");
+            lastActiveUserId = smallestUserId;
+        }
+
+        return lastActiveUserId;
     }
 
     /**
@@ -237,6 +280,41 @@
     }
 
     /**
+     * Gets all the users that are non-ephemeral and can be brought to the foreground on the system.
+     *
+     * @return List of {@code UserInfo} for non-ephemeral users that associated with a real person.
+     */
+    public List<UserInfo> getAllPersistentUsers() {
+        List<UserInfo> users = getAllUsers();
+        for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
+            UserInfo userInfo = iterator.next();
+            if (userInfo.isEphemeral()) {
+                // Remove user that is not admin.
+                iterator.remove();
+            }
+        }
+        return users;
+    }
+
+    /**
+     * Gets all the users that can be brought to the foreground on the system that have admin roles.
+     *
+     * @return List of {@code UserInfo} for admin users that associated with a real person.
+     */
+    public List<UserInfo> getAllAdminUsers() {
+        List<UserInfo> users = getAllUsers();
+
+        for (Iterator<UserInfo> iterator = users.iterator(); iterator.hasNext(); ) {
+            UserInfo userInfo = iterator.next();
+            if (!userInfo.isAdmin()) {
+                // Remove user that is not admin.
+                iterator.remove();
+            }
+        }
+        return users;
+    }
+
+    /**
      * Get all the users except the one with userId passed in.
      *
      * @param userId of the user not to be returned.
@@ -291,12 +369,25 @@
      *
      * @param userInfo User to check against system user.
      * @return {@code true} if is default user, {@code false} otherwise.
+     *
+     * @deprecated Default user is obsolete
      */
+    @Deprecated
     public boolean isDefaultUser(UserInfo userInfo) {
         return userInfo.id == getDefaultBootUser();
     }
 
     /**
+     * Checks whether the user is last active user.
+     *
+     * @param userInfo User to check against last active user.
+     * @return {@code true} if is last active user, {@code false} otherwise.
+     */
+    public boolean isLastActiveUser(UserInfo userInfo) {
+        return userInfo.id == getLastActiveUser();
+    }
+
+    /**
      * Checks whether passed in user is the foreground user.
      *
      * @param userInfo User to check.
@@ -544,10 +635,9 @@
             return false;
         }
 
-        // Not allow to delete the default user for now. Since default user is the one to
-        // boot into.
-        if (isHeadlessSystemUser() && isDefaultUser(userInfo)) {
-            Log.w(TAG, "User " + userInfo.id + " is the default user, could not be removed.");
+        // Not allow to delete the last admin user on the device for now.
+        if (userInfo.isAdmin() && getAllAdminUsers().size() <= 1) {
+            Log.w(TAG, "User " + userInfo.id + " is the last admin user on device.");
             return false;
         }
 
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index a666210..46c762c 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -36,7 +36,7 @@
  *
  * <ol>
  *   <li> Creates a secondary admin user on first run.
- *   <li> Log in to a default user.
+ *   <li> Log in to the last active user.
  * <ol/>
  */
 public class CarUserService extends BroadcastReceiver implements CarServiceBase {
@@ -63,6 +63,7 @@
         }
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
 
         mContext.registerReceiver(this, filter);
     }
@@ -95,8 +96,19 @@
                 // On very first boot, create an admin user and switch to that user.
                 UserInfo admin = mCarUserManagerHelper.createNewAdminUser(OWNER_NAME);
                 mCarUserManagerHelper.switchToUser(admin);
+                mCarUserManagerHelper.setLastActiveUser(
+                        admin.id, /* skipGlobalSettings= */ false);
             } else {
-                mCarUserManagerHelper.switchToUserId(mCarUserManagerHelper.getDefaultBootUser());
+                mCarUserManagerHelper.switchToUserId(mCarUserManagerHelper.getInitialUser());
+            }
+        }
+        if (intent.getAction() == Intent.ACTION_USER_SWITCHED) {
+            UserInfo foregroundUser = mCarUserManagerHelper.getCurrentForegroundUserInfo();
+            // Update last active user if foreground user is not ephemeral.
+            if (!foregroundUser.isEphemeral() && !foregroundUser.isGuest()) {
+                mCarUserManagerHelper.setLastActiveUser(
+                        mCarUserManagerHelper.getCurrentForegroundUserId(),
+                        /* skipGlobalSettings= */ false);
             }
         }
     }
diff --git a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
index 3c97ca1..ca6e027 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java
@@ -19,9 +19,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
 import android.car.user.CarUserManagerHelper;
@@ -40,6 +40,10 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,10 +51,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
 /**
  * This class contains unit tests for the {@link CarUserManagerHelper}.
  * It tests that {@link CarUserManagerHelper} does the right thing for user management flows.
@@ -73,7 +73,7 @@
     @Mock
     private CarUserManagerHelper.OnUsersUpdateListener mTestListener;
 
-    private CarUserManagerHelper mHelper;
+    private CarUserManagerHelper mCarUserManagerHelper;
     private UserInfo mCurrentProcessUser;
     private UserInfo mSystemUser;
     private String mGuestUserName = "testGuest";
@@ -84,16 +84,16 @@
     @Before
     public void setUpMocksAndVariables() throws Exception {
         MockitoAnnotations.initMocks(this);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-        when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager);
-        when(mContext.getResources())
-            .thenReturn(InstrumentationRegistry.getTargetContext().getResources());
-        when(mContext.getApplicationContext()).thenReturn(mContext);
-        mHelper = new CarUserManagerHelper(mContext);
+        doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+        doReturn(mActivityManager).when(mContext).getSystemService(Context.ACTIVITY_SERVICE);
+        doReturn(InstrumentationRegistry.getTargetContext().getResources())
+                .when(mContext).getResources();
+        doReturn(mContext).when(mContext).getApplicationContext();
+        mCarUserManagerHelper = new CarUserManagerHelper(mContext);
 
         mCurrentProcessUser = createUserInfoForId(UserHandle.myUserId());
         mSystemUser = createUserInfoForId(UserHandle.USER_SYSTEM);
-        when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(mCurrentProcessUser);
+        doReturn(mCurrentProcessUser).when(mUserManager).getUserInfo(UserHandle.myUserId());
 
         // Get the ID of the foreground user running this test.
         // We cannot mock the foreground user since getCurrentUser is static.
@@ -111,10 +111,10 @@
         UserInfo testInfo = new UserInfo();
 
         testInfo.id = UserHandle.USER_SYSTEM;
-        assertThat(mHelper.isSystemUser(testInfo)).isTrue();
+        assertThat(mCarUserManagerHelper.isSystemUser(testInfo)).isTrue();
 
         testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
-        assertThat(mHelper.isSystemUser(testInfo)).isFalse();
+        assertThat(mCarUserManagerHelper.isSystemUser(testInfo)).isFalse();
     }
 
     // System user will not be returned when calling get all users.
@@ -131,10 +131,10 @@
         testUsers.add(otherUser2);
         testUsers.add(otherUser3);
 
-        when(mUserManager.getUsers(true)).thenReturn(testUsers);
+        doReturn(testUsers).when(mUserManager).getUsers(true);
 
-        assertThat(mHelper.getAllUsers()).hasSize(3);
-        assertThat(mHelper.getAllUsers())
+        assertThat(mCarUserManagerHelper.getAllUsers()).hasSize(3);
+        assertThat(mCarUserManagerHelper.getAllUsers())
                 .containsExactly(otherUser1, otherUser2, otherUser3);
     }
 
@@ -146,14 +146,14 @@
 
         List<UserInfo> testUsers = Arrays.asList(mForegroundUser, user1, user2);
 
-        when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers));
+        doReturn(new ArrayList<>(testUsers)).when(mUserManager).getUsers(true);
 
         // Should return all 3 users.
-        assertThat(mHelper.getAllUsers()).hasSize(3);
+        assertThat(mCarUserManagerHelper.getAllUsers()).hasSize(3);
 
         // Should return all non-foreground users.
-        assertThat(mHelper.getAllSwitchableUsers()).hasSize(2);
-        assertThat(mHelper.getAllSwitchableUsers()).containsExactly(user1, user2);
+        assertThat(mCarUserManagerHelper.getAllSwitchableUsers()).hasSize(2);
+        assertThat(mCarUserManagerHelper.getAllSwitchableUsers()).containsExactly(user1, user2);
     }
 
     @Test
@@ -162,80 +162,89 @@
 
         // System user cannot be removed.
         testInfo.id = UserHandle.USER_SYSTEM;
-        assertThat(mHelper.canUserBeRemoved(testInfo)).isFalse();
+        assertThat(mCarUserManagerHelper.canUserBeRemoved(testInfo)).isFalse();
 
         testInfo.id = UserHandle.USER_SYSTEM + 2; // Make it different than system id.
-        assertThat(mHelper.canUserBeRemoved(testInfo)).isTrue();
+        assertThat(mCarUserManagerHelper.canUserBeRemoved(testInfo)).isTrue();
     }
 
     @Test
     public void testCurrentProcessCanAddUsers() {
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(false);
-        assertThat(mHelper.canCurrentProcessAddUsers()).isTrue();
+        doReturn(false).when(mUserManager)
+            .hasUserRestriction(UserManager.DISALLOW_ADD_USER);
+        assertThat(mCarUserManagerHelper.canCurrentProcessAddUsers()).isTrue();
 
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)).thenReturn(true);
-        assertThat(mHelper.canCurrentProcessAddUsers()).isFalse();
+        doReturn(true).when(mUserManager)
+            .hasUserRestriction(UserManager.DISALLOW_ADD_USER);
+        assertThat(mCarUserManagerHelper.canCurrentProcessAddUsers()).isFalse();
     }
 
     @Test
     public void testCurrentProcessCanRemoveUsers() {
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(false);
-        assertThat(mHelper.canCurrentProcessRemoveUsers()).isTrue();
+        doReturn(false).when(mUserManager)
+            .hasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
+        assertThat(mCarUserManagerHelper.canCurrentProcessRemoveUsers()).isTrue();
 
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_REMOVE_USER)).thenReturn(true);
-        assertThat(mHelper.canCurrentProcessRemoveUsers()).isFalse();
+        doReturn(true).when(mUserManager)
+            .hasUserRestriction(UserManager.DISALLOW_REMOVE_USER);
+        assertThat(mCarUserManagerHelper.canCurrentProcessRemoveUsers()).isFalse();
     }
 
     @Test
     public void testCurrentProcessCanSwitchUsers() {
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
-        assertThat(mHelper.canCurrentProcessSwitchUsers()).isTrue();
+        doReturn(false).when(mUserManager)
+            .hasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
+        assertThat(mCarUserManagerHelper.canCurrentProcessSwitchUsers()).isTrue();
 
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
-        assertThat(mHelper.canCurrentProcessSwitchUsers()).isFalse();
+        doReturn(true).when(mUserManager)
+            .hasUserRestriction(UserManager.DISALLOW_USER_SWITCH);
+        assertThat(mCarUserManagerHelper.canCurrentProcessSwitchUsers()).isFalse();
     }
 
     @Test
     public void testCurrentGuestProcessCannotModifyAccounts() {
-        assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
+        assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isTrue();
 
-        when(mUserManager.isGuestUser()).thenReturn(true);
-        assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
+        doReturn(true).when(mUserManager).isGuestUser();
+
+        assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isFalse();
     }
 
     @Test
     public void testCurrentDemoProcessCannotModifyAccounts() {
-        assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
+        assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isTrue();
 
-        when(mUserManager.isDemoUser()).thenReturn(true);
-        assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
+        doReturn(true).when(mUserManager).isDemoUser();
+
+        assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isFalse();
     }
 
     @Test
     public void testCurrentDisallowModifyAccountsProcessIsEnforced() {
-        assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue();
+        assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isTrue();
 
-        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS))
-            .thenReturn(true);
-        assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse();
+        doReturn(true).when(mUserManager)
+                .hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS);
+
+        assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isFalse();
     }
 
     @Test
     public void testCreateNewAdminUser() {
         // Make sure current user is admin, since only admins can create other admins.
-        when(mUserManager.isAdminUser()).thenReturn(true);
+        doReturn(true).when(mUserManager).isAdminUser();
 
         // Verify createUser on UserManager gets called.
-        mHelper.createNewAdminUser(mTestUserName);
+        mCarUserManagerHelper.createNewAdminUser(mTestUserName);
         verify(mUserManager).createUser(mTestUserName, UserInfo.FLAG_ADMIN);
 
-        when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(null);
-        assertThat(mHelper.createNewAdminUser(mTestUserName)).isNull();
+        doReturn(null).when(mUserManager).createUser(mTestUserName, UserInfo.FLAG_ADMIN);
+        assertThat(mCarUserManagerHelper.createNewAdminUser(mTestUserName)).isNull();
 
         UserInfo newUser = new UserInfo();
         newUser.name = mTestUserName;
-        when(mUserManager.createUser(mTestUserName, UserInfo.FLAG_ADMIN)).thenReturn(newUser);
-        assertThat(mHelper.createNewAdminUser(mTestUserName)).isEqualTo(newUser);
+        doReturn(newUser).when(mUserManager).createUser(mTestUserName, UserInfo.FLAG_ADMIN);
+        assertThat(mCarUserManagerHelper.createNewAdminUser(mTestUserName)).isEqualTo(newUser);
     }
 
     @Test
@@ -243,11 +252,11 @@
         String newAdminName = "Test new admin";
         UserInfo expectedAdmin = new UserInfo();
         expectedAdmin.name = newAdminName;
-        when(mUserManager.createUser(newAdminName, UserInfo.FLAG_ADMIN)).thenReturn(expectedAdmin);
+        doReturn(expectedAdmin).when(mUserManager).createUser(newAdminName, UserInfo.FLAG_ADMIN);
 
         // Admins can create other admins.
-        when(mUserManager.isAdminUser()).thenReturn(true);
-        UserInfo actualAdmin = mHelper.createNewAdminUser(newAdminName);
+        doReturn(true).when(mUserManager).isAdminUser();
+        UserInfo actualAdmin = mCarUserManagerHelper.createNewAdminUser(newAdminName);
         assertThat(actualAdmin).isEqualTo(expectedAdmin);
     }
 
@@ -256,11 +265,11 @@
         String newAdminName = "Test new admin";
         UserInfo expectedAdmin = new UserInfo();
         expectedAdmin.name = newAdminName;
-        when(mUserManager.createUser(newAdminName, UserInfo.FLAG_ADMIN)).thenReturn(expectedAdmin);
+        doReturn(expectedAdmin).when(mUserManager).createUser(newAdminName, UserInfo.FLAG_ADMIN);
 
         // Test that non-admins cannot create new admins.
-        when(mUserManager.isAdminUser()).thenReturn(false); // Current user non-admin.
-        assertThat(mHelper.createNewAdminUser(newAdminName)).isNull();
+        doReturn(false).when(mUserManager).isAdminUser(); // Current user non-admin.
+        assertThat(mCarUserManagerHelper.createNewAdminUser(newAdminName)).isNull();
     }
 
     @Test
@@ -268,82 +277,99 @@
         String newAdminName = "Test new admin";
         UserInfo expectedAdmin = new UserInfo();
         expectedAdmin.name = newAdminName;
-        when(mUserManager.createUser(newAdminName, UserInfo.FLAG_ADMIN)).thenReturn(expectedAdmin);
+
+        doReturn(expectedAdmin).when(mUserManager).createUser(newAdminName, UserInfo.FLAG_ADMIN);
 
         // System user can create admins.
-        when(mUserManager.isSystemUser()).thenReturn(true);
-        UserInfo actualAdmin = mHelper.createNewAdminUser(newAdminName);
+        doReturn(true).when(mUserManager).isSystemUser();
+        UserInfo actualAdmin = mCarUserManagerHelper.createNewAdminUser(newAdminName);
         assertThat(actualAdmin).isEqualTo(expectedAdmin);
     }
 
     @Test
     public void testCreateNewNonAdminUser() {
         // Verify createUser on UserManager gets called.
-        mHelper.createNewNonAdminUser(mTestUserName);
+        mCarUserManagerHelper.createNewNonAdminUser(mTestUserName);
         verify(mUserManager).createUser(mTestUserName, 0);
 
-        when(mUserManager.createUser(mTestUserName, 0)).thenReturn(null);
-        assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isNull();
+        doReturn(null).when(mUserManager).createUser(mTestUserName, 0);
+        assertThat(mCarUserManagerHelper.createNewNonAdminUser(mTestUserName)).isNull();
 
         UserInfo newUser = new UserInfo();
         newUser.name = mTestUserName;
-        when(mUserManager.createUser(mTestUserName, 0)).thenReturn(newUser);
-        assertThat(mHelper.createNewNonAdminUser(mTestUserName)).isEqualTo(newUser);
+        doReturn(newUser).when(mUserManager).createUser(mTestUserName, 0);
+        assertThat(mCarUserManagerHelper.createNewNonAdminUser(mTestUserName)).isEqualTo(newUser);
     }
 
     @Test
     public void testCannotRemoveSystemUser() {
-        assertThat(mHelper.removeUser(mSystemUser, mGuestUserName)).isFalse();
+        assertThat(mCarUserManagerHelper.removeUser(mSystemUser, mGuestUserName)).isFalse();
     }
 
     @Test
     public void testAdminsCanRemoveOtherUsers() {
         int idToRemove = mCurrentProcessUser.id + 2;
         UserInfo userToRemove = createUserInfoForId(idToRemove);
-        when(mUserManager.removeUser(idToRemove)).thenReturn(true);
+
+        doReturn(true).when(mUserManager).removeUser(idToRemove);
 
         // If Admin is removing non-current, non-system user, simply calls removeUser.
-        when(mUserManager.isAdminUser()).thenReturn(true);
-        assertThat(mHelper.removeUser(userToRemove, mGuestUserName)).isTrue();
+        doReturn(true).when(mUserManager).isAdminUser();
+        assertThat(mCarUserManagerHelper.removeUser(userToRemove, mGuestUserName)).isTrue();
         verify(mUserManager).removeUser(idToRemove);
     }
 
     @Test
-    public void testNonAdminsCanOnlyRemoveThemselves() {
+    public void testNonAdminsCanNotRemoveOtherUsers() {
         UserInfo otherUser = createUserInfoForId(mCurrentProcessUser.id + 2);
 
         // Make current user non-admin.
-        when(mUserManager.isAdminUser()).thenReturn(false);
+        doReturn(false).when(mUserManager).isAdminUser();
 
         // Mock so that removeUser always pretends it's successful.
-        when(mUserManager.removeUser(anyInt())).thenReturn(true);
+        doReturn(true).when(mUserManager).removeUser(anyInt());
 
         // If Non-Admin is trying to remove someone other than themselves, they should fail.
-        assertThat(mHelper.removeUser(otherUser, mGuestUserName)).isFalse();
+        assertThat(mCarUserManagerHelper.removeUser(otherUser, mGuestUserName)).isFalse();
         verify(mUserManager, never()).removeUser(otherUser.id);
     }
 
     @Test
+    public void testRemoveLastActiveUser() {
+        // Cannot remove system user.
+        assertThat(mCarUserManagerHelper.removeUser(mSystemUser, mGuestUserName)).isFalse();
+
+        UserInfo adminInfo = new UserInfo(/* id= */10, "admin", UserInfo.FLAG_ADMIN);
+        List<UserInfo> users = new ArrayList<UserInfo>();
+        users.add(adminInfo);
+
+        doReturn(users).when(mUserManager).getUsers(true);
+
+        assertThat(mCarUserManagerHelper.removeUser(adminInfo, mGuestUserName))
+            .isEqualTo(false);
+    }
+
+    @Test
     public void testSwitchToGuest() {
-        mHelper.startNewGuestSession(mGuestUserName);
+        mCarUserManagerHelper.startNewGuestSession(mGuestUserName);
         verify(mUserManager).createGuest(mContext, mGuestUserName);
 
-        UserInfo guestInfo = new UserInfo(21, mGuestUserName, UserInfo.FLAG_GUEST);
-        when(mUserManager.createGuest(mContext, mGuestUserName)).thenReturn(guestInfo);
-        mHelper.startNewGuestSession(mGuestUserName);
+        UserInfo guestInfo = new UserInfo(/* id= */21, mGuestUserName, UserInfo.FLAG_GUEST);
+        doReturn(guestInfo).when(mUserManager).createGuest(mContext, mGuestUserName);
+        mCarUserManagerHelper.startNewGuestSession(mGuestUserName);
         verify(mActivityManager).switchUser(21);
     }
 
     @Test
     public void testGetUserIcon() {
-        mHelper.getUserIcon(mCurrentProcessUser);
+        mCarUserManagerHelper.getUserIcon(mCurrentProcessUser);
         verify(mUserManager).getUserIcon(mCurrentProcessUser.id);
     }
 
     @Test
     public void testScaleUserIcon() {
         Bitmap fakeIcon = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
-        Drawable scaledIcon = mHelper.scaleUserIcon(fakeIcon, 300);
+        Drawable scaledIcon = mCarUserManagerHelper.scaleUserIcon(fakeIcon, 300);
         assertThat(scaledIcon.getIntrinsicWidth()).isEqualTo(300);
         assertThat(scaledIcon.getIntrinsicHeight()).isEqualTo(300);
     }
@@ -352,17 +378,17 @@
     public void testSetUserName() {
         UserInfo testInfo = createUserInfoForId(mCurrentProcessUser.id + 3);
         String newName = "New Test Name";
-        mHelper.setUserName(testInfo, newName);
+        mCarUserManagerHelper.setUserName(testInfo, newName);
         verify(mUserManager).setUserName(mCurrentProcessUser.id + 3, newName);
     }
 
     @Test
     public void testIsCurrentProcessSystemUser() {
-        when(mUserManager.isAdminUser()).thenReturn(true);
-        assertThat(mHelper.isCurrentProcessAdminUser()).isTrue();
+        doReturn(true).when(mUserManager).isAdminUser();
+        assertThat(mCarUserManagerHelper.isCurrentProcessAdminUser()).isTrue();
 
-        when(mUserManager.isAdminUser()).thenReturn(false);
-        assertThat(mHelper.isCurrentProcessAdminUser()).isFalse();
+        doReturn(false).when(mUserManager).isAdminUser();
+        assertThat(mCarUserManagerHelper.isCurrentProcessAdminUser()).isFalse();
     }
 
     @Test
@@ -371,13 +397,13 @@
         UserInfo testInfo = createUserInfoForId(userId);
 
         // Test that non-admins cannot assign admin privileges.
-        when(mUserManager.isAdminUser()).thenReturn(false); // Current user non-admin.
-        mHelper.assignAdminPrivileges(testInfo);
+        doReturn(false).when(mUserManager).isAdminUser(); // Current user non-admin.
+        mCarUserManagerHelper.assignAdminPrivileges(testInfo);
         verify(mUserManager, never()).setUserAdmin(userId);
 
         // Admins can assign admin privileges.
-        when(mUserManager.isAdminUser()).thenReturn(true);
-        mHelper.assignAdminPrivileges(testInfo);
+        doReturn(true).when(mUserManager).isAdminUser();
+        mCarUserManagerHelper.assignAdminPrivileges(testInfo);
         verify(mUserManager).setUserAdmin(userId);
     }
 
@@ -386,11 +412,13 @@
         int userId = 20;
         UserInfo testInfo = createUserInfoForId(userId);
 
-        mHelper.setUserRestriction(testInfo, UserManager.DISALLOW_ADD_USER, /* enable= */ true);
+        mCarUserManagerHelper.setUserRestriction(
+                testInfo, UserManager.DISALLOW_ADD_USER, /* enable= */ true);
         verify(mUserManager).setUserRestriction(
                 UserManager.DISALLOW_ADD_USER, true, UserHandle.of(userId));
 
-        mHelper.setUserRestriction(testInfo, UserManager.DISALLOW_REMOVE_USER, /* enable= */ false);
+        mCarUserManagerHelper.setUserRestriction(
+                testInfo, UserManager.DISALLOW_REMOVE_USER, /* enable= */ false);
         verify(mUserManager).setUserRestriction(
                 UserManager.DISALLOW_REMOVE_USER, false, UserHandle.of(userId));
     }
@@ -400,9 +428,10 @@
         String testUserName = "Test User";
         int userId = 20;
         UserInfo newNonAdmin = createUserInfoForId(userId);
-        when(mUserManager.createUser(testUserName, /* flags= */ 0)).thenReturn(newNonAdmin);
 
-        mHelper.createNewNonAdminUser(testUserName);
+        doReturn(newNonAdmin).when(mUserManager).createUser(testUserName, /* flags= */ 0);
+
+        mCarUserManagerHelper.createNewNonAdminUser(testUserName);
 
         verify(mUserManager).setUserRestriction(
                 UserManager.DISALLOW_FACTORY_RESET, /* enable= */ true, UserHandle.of(userId));
@@ -417,9 +446,11 @@
         int testUserId = 30;
         boolean restrictionEnabled = false;
         UserInfo testInfo = createUserInfoForId(testUserId);
-        when(mUserManager.isAdminUser()).thenReturn(true); // Only admins can assign privileges.
 
-        mHelper.assignAdminPrivileges(testInfo);
+        // Only admins can assign privileges.
+        doReturn(true).when(mUserManager).isAdminUser();
+
+        mCarUserManagerHelper.assignAdminPrivileges(testInfo);
 
         verify(mUserManager).setUserRestriction(
                 UserManager.DISALLOW_FACTORY_RESET, restrictionEnabled, UserHandle.of(testUserId));
@@ -427,7 +458,7 @@
 
     @Test
     public void testRegisterUserChangeReceiver() {
-        mHelper.registerOnUsersUpdateListener(mTestListener);
+        mCarUserManagerHelper.registerOnUsersUpdateListener(mTestListener);
 
         ArgumentCaptor<BroadcastReceiver> receiverCaptor =
                 ArgumentCaptor.forClass(BroadcastReceiver.class);
@@ -465,10 +496,52 @@
         assertThat(handlerCaptor.getValue()).isNull();
 
         // Unregister the receiver.
-        mHelper.unregisterOnUsersUpdateListener();
+        mCarUserManagerHelper.unregisterOnUsersUpdateListener();
         verify(mContext).unregisterReceiver(receiverCaptor.getValue());
     }
 
+    @Test
+    public void testGetInitialUserWithValidLastActiveUser() {
+        SystemProperties.set("android.car.systemuser.headless", "true");
+        int lastActiveUserId = 12;
+
+        UserInfo otherUser1 = createUserInfoForId(lastActiveUserId - 2);
+        UserInfo otherUser2 = createUserInfoForId(lastActiveUserId - 1);
+        UserInfo otherUser3 = createUserInfoForId(lastActiveUserId);
+
+        List<UserInfo> testUsers = new ArrayList<>();
+        testUsers.add(mSystemUser);
+        testUsers.add(otherUser1);
+        testUsers.add(otherUser2);
+        testUsers.add(otherUser3);
+
+        mCarUserManagerHelper.setLastActiveUser(
+                lastActiveUserId, /* skipGlobalSettings= */ true);
+        doReturn(testUsers).when(mUserManager).getUsers(true);
+
+        assertThat(mCarUserManagerHelper.getInitialUser()).isEqualTo(lastActiveUserId);
+    }
+
+    @Test
+    public void testGetInitialUserWithNonExistLastActiveUser() {
+        SystemProperties.set("android.car.systemuser.headless", "true");
+        int lastActiveUserId = 12;
+
+        UserInfo otherUser1 = createUserInfoForId(lastActiveUserId - 2);
+        UserInfo otherUser2 = createUserInfoForId(lastActiveUserId - 1);
+
+        List<UserInfo> testUsers = new ArrayList<>();
+        testUsers.add(mSystemUser);
+        testUsers.add(otherUser1);
+        testUsers.add(otherUser2);
+
+        mCarUserManagerHelper.setLastActiveUser(
+                lastActiveUserId, /* skipGlobalSettings= */ true);
+        doReturn(testUsers).when(mUserManager).getUsers(true);
+
+        assertThat(mCarUserManagerHelper.getInitialUser()).isEqualTo(lastActiveUserId - 2);
+    }
+
     private UserInfo createUserInfoForId(int id) {
         UserInfo userInfo = new UserInfo();
         userInfo.id = id;
diff --git a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
index 20cb060..a6b48bf 100644
--- a/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/user/CarUserServiceTest.java
@@ -84,9 +84,10 @@
         mCarUserService.init();
         verify(mMockContext).registerReceiver(eq(mCarUserService), argument.capture());
         IntentFilter intentFilter = argument.getValue();
-        assertThat(intentFilter.countActions()).isEqualTo(1);
+        assertThat(intentFilter.countActions()).isEqualTo(2);
 
         assertThat(intentFilter.getAction(0)).isEqualTo(Intent.ACTION_LOCKED_BOOT_COMPLETED);
+        assertThat(intentFilter.getAction(1)).isEqualTo(Intent.ACTION_USER_SWITCHED);
     }
 
     /**
@@ -139,4 +140,47 @@
         verify(mCarUserManagerHelper).
                 setUserRestriction(user0, UserManager.DISALLOW_MODIFY_ACCOUNTS, true);
     }
+
+    /**
+     * Test that the {@link CarUserService} starts up the last active user on reboot.
+     */
+    @Test
+    public void testStartsLastActiveUserOnReboot() {
+        List<UserInfo> users = new ArrayList<>();
+
+        int adminUserId = 10;
+        UserInfo admin = new UserInfo(adminUserId, CarUserService.OWNER_NAME, UserInfo.FLAG_ADMIN);
+
+        int secUserId = 11;
+        UserInfo secUser =
+                new UserInfo(secUserId, CarUserService.OWNER_NAME, UserInfo.FLAG_ADMIN);
+
+        users.add(admin);
+        users.add(secUser);
+
+        doReturn(users).when(mCarUserManagerHelper).getAllUsers();
+        doReturn(secUserId).when(mCarUserManagerHelper).getLastActiveUser();
+
+        mCarUserService.onReceive(mMockContext,
+                new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED));
+
+        verify(mCarUserManagerHelper).switchToUserId(secUserId);
+    }
+
+    /**
+     * Test that the {@link CarUserService} updates last active user on user switch intent.
+     */
+    @Test
+    public void testLastActiveUserUpdatedOnUserSwitch() {
+        int lastActiveUserId = 11;
+
+        doReturn(false).when(mCarUserManagerHelper).isForegroundUserGuest();
+        doReturn(lastActiveUserId).when(mCarUserManagerHelper).getCurrentForegroundUserId();
+
+        mCarUserService.onReceive(mMockContext,
+                new Intent(Intent.ACTION_USER_SWITCHED));
+
+        verify(mCarUserManagerHelper).setLastActiveUser(
+                lastActiveUserId, /* skipGlobalSetting= */ false);
+    }
 }