Fixed CarUserService.onUserSwitching() check for headless system user.

Test: atest CarUserServiceTest

Bug: 156299496
Fixes: 152759203
Change-Id: I46b8441912b807a3aa45b75106b9785dadabcf46
diff --git a/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java b/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
index 4a26391..cd6028c 100644
--- a/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
+++ b/car-test-lib/src/android/car/test/mocks/AndroidMockitoHelper.java
@@ -29,6 +29,7 @@
 import android.os.IBinder;
 import android.os.IInterface;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.os.UserManager;
 
 import java.util.Arrays;
@@ -75,10 +76,27 @@
     public static UserInfo mockUmGetUserInfo(@NonNull UserManager um, @UserIdInt int userId,
             @UserInfoFlag int flags) {
         Objects.requireNonNull(um);
-        UserInfo userInfo = new UserTestingHelper.UserInfoBuilder(userId).setFlags(flags).build();
-        when(um.getUserInfo(userId)).thenReturn(userInfo);
+        UserInfo user = new UserTestingHelper.UserInfoBuilder(userId).setFlags(flags).build();
+        mockUmGetUserInfo(um, user);
+        return user;
+    }
 
-        return userInfo;
+    /**
+     * Mocks {@code UserManager.getUserInfo(userId)} to return the given {@link UserInfo}.
+     */
+    @NonNull
+    public static void mockUmGetUserInfo(@NonNull UserManager um, @NonNull UserInfo user) {
+        when(um.getUserInfo(user.id)).thenReturn(user);
+    }
+
+    /**
+     * Mocks {@code UserManager.getUserInfo(userId)} when the {@code userId} is the system user's.
+     */
+    @NonNull
+    public static void mockUmGetSystemUser(@NonNull UserManager um) {
+        UserInfo user = new UserTestingHelper.UserInfoBuilder(UserHandle.USER_SYSTEM)
+                .setFlags(UserInfo.FLAG_SYSTEM).build();
+        when(um.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(user);
     }
 
     /**
diff --git a/service/src/com/android/car/user/CarUserService.java b/service/src/com/android/car/user/CarUserService.java
index 00502d1..4292ff8 100644
--- a/service/src/com/android/car/user/CarUserService.java
+++ b/service/src/com/android/car/user/CarUserService.java
@@ -39,6 +39,7 @@
 import android.car.userlib.CommonConstants.CarUserServiceConstants;
 import android.car.userlib.HalCallback;
 import android.car.userlib.UserHalHelper;
+import android.car.userlib.UserHelper;
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
@@ -1410,7 +1411,7 @@
         // Switch HAL users if user switch is not requested by CarUserService
         notifyHalLegacySwitch(fromUserId, toUserId);
 
-        if (!isSystemUser(toUserId)) {
+        if (!UserHelper.isHeadlessSystemUser(toUserId)) {
             mCarUserManagerHelper.setLastActiveUser(toUserId);
         }
         if (mLastPassengerId != UserHandle.USER_NULL) {
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 f031686..c44ea24 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
@@ -16,6 +16,7 @@
 
 package com.android.car.user;
 
+import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetSystemUser;
 import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetUserInfo;
 import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetUsers;
 import static android.car.test.util.UserTestingHelper.UserInfoBuilder;
@@ -54,6 +55,7 @@
 import android.car.CarOccupantZoneManager.OccupantZoneInfo;
 import android.car.settings.CarSettings;
 import android.car.test.mocks.AbstractExtendedMockitoTestCase;
+import android.car.test.mocks.AndroidMockitoHelper;
 import android.car.test.mocks.BlockingAnswer;
 import android.car.test.util.BlockingResultReceiver;
 import android.car.testapi.BlockingUserLifecycleListener;
@@ -66,6 +68,7 @@
 import android.car.userlib.CarUserManagerHelper;
 import android.car.userlib.HalCallback;
 import android.car.userlib.UserHalHelper;
+import android.car.userlib.UserHelper;
 import android.content.Context;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
@@ -177,7 +180,11 @@
     @Override
     protected void onSessionBuilder(CustomMockitoSessionBuilder builder) {
         builder
-            .spyStatic(ActivityManager.class);
+            .spyStatic(ActivityManager.class)
+            // TODO(b/156299496): it cannot spy on UserManager, as it would slow down the tests
+            // considerably (more than 5 minutes total, instead of just a couple seconds). So, it's
+            // mocking UserHelper.isHeadlessSystemUser() (on mockIsHeadlessSystemUser()) instead...
+            .spyStatic(UserHelper.class);
     }
 
     /**
@@ -221,7 +228,7 @@
     }
 
     @Test
-    public void testOnUserLifecycleEvent_nofityListener() throws Exception {
+    public void testOnUserLifecycleEvent_notifyListener() throws Exception {
         // Arrange
         mCarUserService.addUserLifecycleListener(mUserLifecycleListener);
         mockExistingUsers();
@@ -262,6 +269,14 @@
         assertThat(actualEvent.getUserId()).isEqualTo(expectedNewUserId);
     }
 
+    private void verifyLastActiveUserSet(@UserIdInt int userId) {
+        verify(mMockedCarUserManagerHelper).setLastActiveUser(userId);
+    }
+
+    private void verifyLastActiveUserNotSet() {
+        verify(mMockedCarUserManagerHelper, never()).setLastActiveUser(anyInt());
+    }
+
     /**
      * Test that the {@link CarUserService} disables the location service for headless user 0 upon
      * first run.
@@ -277,10 +292,24 @@
      * Test that the {@link CarUserService} updates last active user on user switch.
      */
     @Test
-    public void testLastActiveUserUpdatedOnUserSwitch() throws Exception {
+    public void testLastActiveUserUpdatedOnUserSwitch_nonHeadlessSystemUser() throws Exception {
+        mockIsHeadlessSystemUser(mRegularUser.id, false);
         mockExistingUsers();
+
         sendUserSwitchingEvent(mAdminUser.id, mRegularUser.id);
-        verify(mMockedCarUserManagerHelper).setLastActiveUser(mRegularUser.id);
+
+        verifyLastActiveUserSet(mRegularUser.id);
+    }
+
+    @Test
+    public void testLastActiveUserUpdatedOnUserSwitch_headlessSystemUser() throws Exception {
+        mockIsHeadlessSystemUser(mRegularUser.id, true);
+        mockUmGetSystemUser(mMockedUserManager);
+        mockExistingUsers();
+
+        sendUserSwitchingEvent(mAdminUser.id, UserHandle.USER_SYSTEM);
+
+        verifyLastActiveUserNotSet();
     }
 
     /**
@@ -1321,7 +1350,7 @@
     private void mockExistingUsers() {
         mockUmGetUsers(mMockedUserManager, mExistingUsers);
         for (UserInfo user : mExistingUsers) {
-            when(mMockedUserManager.getUserInfo(user.id)).thenReturn(user);
+            AndroidMockitoHelper.mockUmGetUserInfo(mMockedUserManager, user);
         }
     }
 
@@ -1348,6 +1377,10 @@
                 eq(usersInfo), notNull());
     }
 
+    private void mockIsHeadlessSystemUser(@UserIdInt int userId, boolean mode) {
+        doReturn(mode).when(() -> UserHelper.isHeadlessSystemUser(userId));
+    }
+
     private void mockHalSwitch(@UserIdInt int currentUserId, @NonNull UserInfo androidTargetUser,
             @Nullable SwitchUserResponse response) {
         mockHalSwitch(currentUserId, HalCallback.STATUS_OK, response, androidTargetUser);