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);