diff options
author | Bill Yi <byi@google.com> | 2018-11-28 18:35:00 -0800 |
---|---|---|
committer | Bill Yi <byi@google.com> | 2018-11-28 18:35:00 -0800 |
commit | 0f8320f6b95736ea4b703764a7d11a8a6ca13674 (patch) | |
tree | d7b300e81f05e45345ada1ffcaf39b2512dd8f6f /tests/carservice_unit_test/src/com/android/car | |
parent | f02b56678700a4035d0ad8882f7d20371bb96ee2 (diff) | |
parent | 911e6566751a60c29eada6ad0679694bed11be4f (diff) | |
download | Car-pie-platform-release.tar.gz |
Merge pi-qpr1-release PQ1A.181105.017.A1 to pi-platform-releasepie-platform-releasepie-cuttlefish-testing
Change-Id: Ibafbc25e1d704d7e84a168b32d35a165dd41e06f
Diffstat (limited to 'tests/carservice_unit_test/src/com/android/car')
3 files changed, 698 insertions, 145 deletions
diff --git a/tests/carservice_unit_test/src/com/android/car/CarLocationServiceTest.java b/tests/carservice_unit_test/src/com/android/car/CarLocationServiceTest.java index 8ac7d9b1db..b071e9947d 100644 --- a/tests/carservice_unit_test/src/com/android/car/CarLocationServiceTest.java +++ b/tests/carservice_unit_test/src/com/android/car/CarLocationServiceTest.java @@ -31,6 +31,7 @@ import android.car.hardware.CarSensorEvent; import android.car.hardware.CarSensorManager; import android.car.hardware.property.CarPropertyEvent; import android.car.hardware.property.ICarPropertyEventListener; +import android.car.user.CarUserManagerHelper; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -72,7 +73,9 @@ import java.util.stream.Collectors; * The following mocks are used: * 1. {@link Context} provides files and a mocked {@link LocationManager}. * 2. {@link LocationManager} provides dummy {@link Location}s. - * 3. {@link CarSensorService} registers a handler for sensor events and sends ignition-off events. + * 3. {@link CarPropertyService} registers a listener for ignition state events. + * 3. {@link CarPowerManagementService} registers a handler for power events. + * 4. {@link CarUserManagerHelper} tells whether or not the system user is headless. */ @RunWith(AndroidJUnit4.class) public class CarLocationServiceTest { @@ -85,6 +88,7 @@ public class CarLocationServiceTest { @Mock private LocationManager mMockLocationManager; @Mock private CarPropertyService mMockCarPropertyService; @Mock private CarPowerManagementService mMockCarPowerManagementService; + @Mock private CarUserManagerHelper mMockCarUserManagerHelper; /** * Initialize all of the objects with the @Mock annotation. @@ -95,7 +99,7 @@ public class CarLocationServiceTest { mContext = InstrumentationRegistry.getTargetContext(); mLatch = new CountDownLatch(1); mCarLocationService = new CarLocationService(mMockContext, mMockCarPowerManagementService, - mMockCarPropertyService) { + mMockCarPropertyService, mMockCarUserManagerHelper) { @Override void asyncOperation(Runnable operation) { super.asyncOperation(() -> { @@ -143,12 +147,13 @@ public class CarLocationServiceTest { mCarLocationService); verify(mMockContext).registerReceiver(eq(mCarLocationService), argument.capture()); IntentFilter intentFilter = argument.getValue(); - assertEquals(3, intentFilter.countActions()); + assertEquals(4, intentFilter.countActions()); String[] actions = {intentFilter.getAction(0), intentFilter.getAction(1), - intentFilter.getAction(2)}; + intentFilter.getAction(2), intentFilter.getAction(3)}; assertTrue(ArrayUtils.contains(actions, Intent.ACTION_LOCKED_BOOT_COMPLETED)); assertTrue(ArrayUtils.contains(actions, LocationManager.MODE_CHANGED_ACTION)); assertTrue(ArrayUtils.contains(actions, LocationManager.GPS_ENABLED_CHANGE_ACTION)); + assertTrue(ArrayUtils.contains(actions, Intent.ACTION_USER_SWITCHED)); verify(mMockCarPropertyService).registerListener( eq(CarSensorManager.SENSOR_TYPE_IGNITION_STATE), eq(0.0f), any()); } @@ -166,10 +171,11 @@ public class CarLocationServiceTest { /** * Test that the {@link CarLocationService} parses a location from a JSON serialization and then - * injects it into the {@link LocationManager} upon boot complete. + * injects it into the {@link LocationManager} upon boot complete if the system user is not + * headless. */ @Test - public void testLoadsLocation() throws IOException, InterruptedException { + public void testLoadsLocationOnLockedBootComplete() throws IOException, InterruptedException { long currentTime = System.currentTimeMillis(); long elapsedTime = SystemClock.elapsedRealtimeNanos(); long pastTime = currentTime - 60000; @@ -181,6 +187,7 @@ public class CarLocationServiceTest { when(mMockLocationManager.injectLocation(argument.capture())).thenReturn(true); when(mMockContext.getFileStreamPath("location_cache.json")) .thenReturn(mContext.getFileStreamPath(TEST_FILENAME)); + when(mMockCarUserManagerHelper.isHeadlessSystemUser()).thenReturn(false); mCarLocationService.onReceive(mMockContext, new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)); @@ -196,6 +203,39 @@ public class CarLocationServiceTest { } /** + * Test that the {@link CarLocationService} parses a location from a JSON seialization and then + * injects it into the {@link LocationManager} upon user switch if the system user is headless. + */ + @Test + public void testLoadsLocationWithHeadlessSystemUser() throws IOException, InterruptedException { + long currentTime = System.currentTimeMillis(); + long elapsedTime = SystemClock.elapsedRealtimeNanos(); + long pastTime = currentTime - 60000; + writeCacheFile("{\"provider\": \"gps\", \"latitude\": 16.7666, \"longitude\": 3.0026," + + "\"accuracy\":12.3, \"captureTime\": " + pastTime + "}"); + ArgumentCaptor<Location> argument = ArgumentCaptor.forClass(Location.class); + when(mMockContext.getSystemService(Context.LOCATION_SERVICE)) + .thenReturn(mMockLocationManager); + when(mMockLocationManager.injectLocation(argument.capture())).thenReturn(true); + when(mMockContext.getFileStreamPath("location_cache.json")) + .thenReturn(mContext.getFileStreamPath(TEST_FILENAME)); + when(mMockCarUserManagerHelper.isHeadlessSystemUser()).thenReturn(true); + + Intent userSwitchedIntent = new Intent(Intent.ACTION_USER_SWITCHED); + userSwitchedIntent.putExtra(Intent.EXTRA_USER_HANDLE, 11); + mCarLocationService.onReceive(mMockContext, userSwitchedIntent); + mLatch.await(); + + Location location = argument.getValue(); + assertEquals("gps", location.getProvider()); + assertEquals(16.7666, location.getLatitude()); + assertEquals(3.0026, location.getLongitude()); + assertEquals(12.3f, location.getAccuracy()); + assertTrue(location.getTime() >= currentTime); + assertTrue(location.getElapsedRealtimeNanos() >= elapsedTime); + } + + /** * Test that the {@link CarLocationService} does not inject a location if there is no location * cache file. */ 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 44cc0d6ae5..7f53da5655 100644 --- a/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java +++ b/tests/carservice_unit_test/src/com/android/car/CarUserManagerHelperTest.java @@ -18,8 +18,12 @@ package com.android.car; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.car.user.CarUserManagerHelper; @@ -30,11 +34,13 @@ import android.content.IntentFilter; import android.content.pm.UserInfo; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.os.Handler; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; @@ -42,6 +48,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -54,10 +61,11 @@ import java.util.List; * The following mocks are used: * 1. {@link Context} provides system services and resources. * 2. {@link UserManager} provides dummy users and user info. - * 3. {@link ActivityManager} provides dummy current process user. + * 3. {@link ActivityManager} to verify user switch is invoked. * 4. {@link CarUserManagerHelper.OnUsersUpdateListener} registers a listener for user updates. */ @RunWith(AndroidJUnit4.class) +@SmallTest public class CarUserManagerHelperTest { @Mock private Context mContext; @@ -68,25 +76,37 @@ public class CarUserManagerHelperTest { @Mock private CarUserManagerHelper.OnUsersUpdateListener mTestListener; - private CarUserManagerHelper mHelper; + private CarUserManagerHelper mCarUserManagerHelper; private UserInfo mCurrentProcessUser; private UserInfo mSystemUser; private String mGuestUserName = "testGuest"; private String mTestUserName = "testUser"; + private int mForegroundUserId; + private UserInfo mForegroundUser; @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. + // We cannot rely on foreground_id != system_id, they could be the same user. + mForegroundUserId = ActivityManager.getCurrentUser(); + mForegroundUser = createUserInfoForId(mForegroundUserId); + + // Restore the non-headless state before every test. Individual tests can set the property + // to true to test the headless system user scenario. + SystemProperties.set("android.car.systemuser.headless", "false"); } @Test @@ -94,10 +114,10 @@ public class CarUserManagerHelperTest { 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. @@ -108,92 +128,67 @@ public class CarUserManagerHelperTest { UserInfo otherUser2 = createUserInfoForId(11); UserInfo otherUser3 = createUserInfoForId(12); - List<UserInfo> testUsers = new ArrayList<>(); - testUsers.add(mSystemUser); - testUsers.add(otherUser1); - testUsers.add(otherUser2); - testUsers.add(otherUser3); + mockGetUsers(mSystemUser, otherUser1, otherUser2, otherUser3); - when(mUserManager.getUsers(true)).thenReturn(testUsers); - - // Should return 3 users that don't have SYSTEM USER id. - assertThat(mHelper.getAllUsers()).hasSize(3); - assertThat(mHelper.getAllUsers()) - .containsExactly(otherUser1, otherUser2, otherUser3); + assertThat(mCarUserManagerHelper.getAllUsers()) + .containsExactly(otherUser1, otherUser2, otherUser3); } @Test - public void testHeadlessUser0GetAllUsersWithActiveForegroundUser_NotReturnSystemUser() { - SystemProperties.set("android.car.systemuser.headless", "true"); - mCurrentProcessUser = createUserInfoForId(10); - - UserInfo otherUser1 = createUserInfoForId(11); - UserInfo otherUser2 = createUserInfoForId(12); - UserInfo otherUser3 = createUserInfoForId(13); + public void testGetAllSwitchableUsers() { + // Create two non-foreground users. + UserInfo user1 = createUserInfoForId(mForegroundUserId + 1); + UserInfo user2 = createUserInfoForId(mForegroundUserId + 2); - List<UserInfo> testUsers = new ArrayList<>(); - testUsers.add(mSystemUser); - testUsers.add(mCurrentProcessUser); - testUsers.add(otherUser1); - testUsers.add(otherUser2); - testUsers.add(otherUser3); + mockGetUsers(mForegroundUser, user1, user2); - when(mUserManager.getUsers(true)).thenReturn(testUsers); + // Should return all non-foreground users. + assertThat(mCarUserManagerHelper.getAllSwitchableUsers()).containsExactly(user1, user2); + } - assertThat(mHelper.getAllUsers().size()).isEqualTo(4); - assertThat(mHelper.getAllUsers()) - .containsExactly(mCurrentProcessUser, otherUser1, otherUser2, otherUser3); + @Test + public void testGetAllPersistentUsers() { + // Create two non-ephemeral users. + UserInfo user1 = createUserInfoForId(mForegroundUserId); + UserInfo user2 = createUserInfoForId(mForegroundUserId + 1); + // Create two ephemeral users. + UserInfo user3 = new UserInfo( + /* id= */mForegroundUserId + 2, /* name = */ "user3", UserInfo.FLAG_EPHEMERAL); + UserInfo user4 = new UserInfo( + /* id= */mForegroundUserId + 3, /* name = */ "user4", UserInfo.FLAG_EPHEMERAL); + + mockGetUsers(user1, user2, user3, user4); + + // Should return all non-ephemeral users. + assertThat(mCarUserManagerHelper.getAllPersistentUsers()).containsExactly(user1, user2); } @Test - public void testGetAllSwitchableUsers() { - UserInfo user1 = createUserInfoForId(10); + public void testGetAllAdminUsers() { + // Create two admin, and two non-admin users. + UserInfo user1 = new UserInfo(/* id= */ 10, /* name = */ "user10", UserInfo.FLAG_ADMIN); UserInfo user2 = createUserInfoForId(11); UserInfo user3 = createUserInfoForId(12); + UserInfo user4 = new UserInfo(/* id= */ 13, /* name = */ "user13", UserInfo.FLAG_ADMIN); - List<UserInfo> testUsers = new ArrayList<>(); - testUsers.add(mSystemUser); - testUsers.add(user1); - testUsers.add(user2); - testUsers.add(user3); - - when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers)); - - // Should return all 3 non-system users. - assertThat(mHelper.getAllUsers().size()) - .isEqualTo(3); + mockGetUsers(user1, user2, user3, user4); - when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1); - // Should return user 10, 11 and 12. - assertThat(mHelper.getAllSwitchableUsers().size()) - .isEqualTo(3); - assertThat(mHelper.getAllSwitchableUsers()).contains(user1); - assertThat(mHelper.getAllSwitchableUsers()).contains(user2); - assertThat(mHelper.getAllSwitchableUsers()).contains(user3); + // Should return only admin users. + assertThat(mCarUserManagerHelper.getAllAdminUsers()).containsExactly(user1, user4); } - // Get all users for headless user 0 model should exclude system user by default. @Test - public void testHeadlessUser0GetAllSwitchableUsers() { - SystemProperties.set("android.car.systemuser.headless", "true"); + public void testGetAllUsersExceptGuests() { + // Create two users and a guest user. UserInfo user1 = createUserInfoForId(10); - UserInfo user2 = createUserInfoForId(11); - UserInfo user3 = createUserInfoForId(12); - - List<UserInfo> testUsers = new ArrayList<>(); - testUsers.add(mSystemUser); - testUsers.add(user1); - testUsers.add(user2); - testUsers.add(user3); + UserInfo user2 = createUserInfoForId(12); + UserInfo user3 = new UserInfo(/* id= */ 13, /* name = */ "user13", UserInfo.FLAG_GUEST); - when(mUserManager.getUsers(true)).thenReturn(new ArrayList<>(testUsers)); + mockGetUsers(user1, user2, user3); - // Should return all 3 non-system users. - assertThat(mHelper.getAllUsers()).hasSize(3); - - when(mUserManager.getUserInfo(UserHandle.myUserId())).thenReturn(user1); - // Should return user 10, 11 and 12. - assertThat(mHelper.getAllSwitchableUsers()).containsExactly(user1, user2, user3); + // Should not return guests. + assertThat(mCarUserManagerHelper.getAllUsersExceptGuests()) + .containsExactly(user1, user2); } @Test @@ -202,127 +197,304 @@ public class CarUserManagerHelperTest { // 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(); + + doReturn(true).when(mUserManager).isGuestUser(); - when(mUserManager.isGuestUser()).thenReturn(true); - assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse(); + assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isFalse(); } @Test public void testCurrentDemoProcessCannotModifyAccounts() { - assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue(); + assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isTrue(); + + doReturn(true).when(mUserManager).isDemoUser(); - when(mUserManager.isDemoUser()).thenReturn(true); - assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse(); + assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isFalse(); } @Test public void testCurrentDisallowModifyAccountsProcessIsEnforced() { - assertThat(mHelper.canCurrentProcessModifyAccounts()).isTrue(); + assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isTrue(); + + doReturn(true).when(mUserManager) + .hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS); + + assertThat(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).isFalse(); + } + + @Test + public void testGetMaxSupportedUsers() { + SystemProperties.set("fw.max_users", "11"); + + assertThat(mCarUserManagerHelper.getMaxSupportedUsers()).isEqualTo(11); + + // In headless user 0 model, we want to exclude the system user. + SystemProperties.set("android.car.systemuser.headless", "true"); + assertThat(mCarUserManagerHelper.getMaxSupportedUsers()).isEqualTo(10); + } + + @Test + public void testGetMaxSupportedRealUsers() { + SystemProperties.set("fw.max_users", "7"); + + // Create three managed profiles, and two normal users. + UserInfo user1 = createUserInfoForId(10); + UserInfo user2 = + new UserInfo(/* id= */ 11, /* name = */ "user11", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user3 = + new UserInfo(/* id= */ 12, /* name = */ "user12", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user4 = createUserInfoForId(13); + UserInfo user5 = + new UserInfo(/* id= */ 14, /* name = */ "user14", UserInfo.FLAG_MANAGED_PROFILE); + + mockGetUsers(user1, user2, user3, user4, user5); + + // Max users - # managed profiles. + assertThat(mCarUserManagerHelper.getMaxSupportedRealUsers()).isEqualTo(4); + } + + @Test + public void testIsUserLimitReached() { + UserInfo user1 = createUserInfoForId(10); + UserInfo user2 = + new UserInfo(/* id= */ 11, /* name = */ "user11", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user3 = + new UserInfo(/* id= */ 12, /* name = */ "user12", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user4 = createUserInfoForId(13); - when(mUserManager.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) - .thenReturn(true); - assertThat(mHelper.canCurrentProcessModifyAccounts()).isFalse(); + mockGetUsers(user1, user2, user3, user4); + + SystemProperties.set("fw.max_users", "5"); + assertThat(mCarUserManagerHelper.isUserLimitReached()).isFalse(); + + SystemProperties.set("fw.max_users", "4"); + assertThat(mCarUserManagerHelper.isUserLimitReached()).isTrue(); + } + + @Test + public void testHeadlessSystemUser_IsUserLimitReached() { + SystemProperties.set("android.car.systemuser.headless", "true"); + UserInfo user1 = createUserInfoForId(10); + UserInfo user2 = + new UserInfo(/* id= */ 11, /* name = */ "user11", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user3 = + new UserInfo(/* id= */ 12, /* name = */ "user12", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user4 = createUserInfoForId(13); + + mockGetUsers(mSystemUser, user1, user2, user3, user4); + + SystemProperties.set("fw.max_users", "6"); + assertThat(mCarUserManagerHelper.isUserLimitReached()).isFalse(); + + SystemProperties.set("fw.max_users", "5"); + assertThat(mCarUserManagerHelper.isUserLimitReached()).isTrue(); + } + + @Test + public void testIsUserLimitReachedIgnoresGuests() { + SystemProperties.set("fw.max_users", "5"); + + UserInfo user1 = createUserInfoForId(10); + UserInfo user2 = + new UserInfo(/* id= */ 11, /* name = */ "user11", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user3 = + new UserInfo(/* id= */ 12, /* name = */ "user12", UserInfo.FLAG_MANAGED_PROFILE); + UserInfo user4 = createUserInfoForId(13); + UserInfo user5 = new UserInfo(/* id= */ 14, /* name = */ "user14", UserInfo.FLAG_GUEST); + UserInfo user6 = createUserInfoForId(15); + + mockGetUsers(user1, user2, user3, user4); + assertThat(mCarUserManagerHelper.isUserLimitReached()).isFalse(); + + // Add guest user. Verify it doesn't affect the limit. + mockGetUsers(user1, user2, user3, user4, user5); + assertThat(mCarUserManagerHelper.isUserLimitReached()).isFalse(); + + // Add normal user. Limit is reached + mockGetUsers(user1, user2, user3, user4, user5, user6); + assertThat(mCarUserManagerHelper.isUserLimitReached()).isTrue(); } @Test public void testCreateNewAdminUser() { + // Make sure current user is admin, since only admins can create other admins. + 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 + public void testAdminsCanCreateAdmins() { + String newAdminName = "Test new admin"; + UserInfo expectedAdmin = new UserInfo(); + expectedAdmin.name = newAdminName; + doReturn(expectedAdmin).when(mUserManager).createUser(newAdminName, UserInfo.FLAG_ADMIN); + + // Admins can create other admins. + doReturn(true).when(mUserManager).isAdminUser(); + UserInfo actualAdmin = mCarUserManagerHelper.createNewAdminUser(newAdminName); + assertThat(actualAdmin).isEqualTo(expectedAdmin); + } + + @Test + public void testNonAdminsCanNotCreateAdmins() { + String newAdminName = "Test new admin"; + UserInfo expectedAdmin = new UserInfo(); + expectedAdmin.name = newAdminName; + doReturn(expectedAdmin).when(mUserManager).createUser(newAdminName, UserInfo.FLAG_ADMIN); + + // Test that non-admins cannot create new admins. + doReturn(false).when(mUserManager).isAdminUser(); // Current user non-admin. + assertThat(mCarUserManagerHelper.createNewAdminUser(newAdminName)).isNull(); + } + + @Test + public void testSystemUserCanCreateAdmins() { + String newAdminName = "Test new admin"; + UserInfo expectedAdmin = new UserInfo(); + expectedAdmin.name = newAdminName; + + doReturn(expectedAdmin).when(mUserManager).createUser(newAdminName, UserInfo.FLAG_ADMIN); + + // System user can create admins. + 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(mCarUserManagerHelper.removeUser(mSystemUser, mGuestUserName)).isFalse(); + } + + @Test + public void testAdminsCanRemoveOtherUsers() { + int idToRemove = mCurrentProcessUser.id + 2; + UserInfo userToRemove = createUserInfoForId(idToRemove); + + doReturn(true).when(mUserManager).removeUser(idToRemove); + + // If Admin is removing non-current, non-system user, simply calls removeUser. + doReturn(true).when(mUserManager).isAdminUser(); + assertThat(mCarUserManagerHelper.removeUser(userToRemove, mGuestUserName)).isTrue(); + verify(mUserManager).removeUser(idToRemove); + } + + @Test + public void testNonAdminsCanNotRemoveOtherUsers() { + UserInfo otherUser = createUserInfoForId(mCurrentProcessUser.id + 2); + + // Make current user non-admin. + doReturn(false).when(mUserManager).isAdminUser(); + + // Mock so that removeUser always pretends it's successful. + doReturn(true).when(mUserManager).removeUser(anyInt()); + + // If Non-Admin is trying to remove someone other than themselves, they should fail. + assertThat(mCarUserManagerHelper.removeUser(otherUser, mGuestUserName)).isFalse(); + verify(mUserManager, never()).removeUser(otherUser.id); } @Test - public void testRemoveUser() { + public void testRemoveLastActiveUser() { // Cannot remove system user. - assertThat(mHelper.removeUser(mSystemUser, mGuestUserName)).isFalse(); + assertThat(mCarUserManagerHelper.removeUser(mSystemUser, mGuestUserName)).isFalse(); - // Removing non-current, non-system user, simply calls removeUser. - UserInfo userToRemove = createUserInfoForId(mCurrentProcessUser.id + 2); + UserInfo adminInfo = new UserInfo(/* id= */10, "admin", UserInfo.FLAG_ADMIN); + mockGetUsers(adminInfo); - mHelper.removeUser(userToRemove, mGuestUserName); - verify(mUserManager).removeUser(mCurrentProcessUser.id + 2); + 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); } @@ -331,13 +503,107 @@ public class CarUserManagerHelperTest { 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() { + doReturn(true).when(mUserManager).isAdminUser(); + assertThat(mCarUserManagerHelper.isCurrentProcessAdminUser()).isTrue(); + + doReturn(false).when(mUserManager).isAdminUser(); + assertThat(mCarUserManagerHelper.isCurrentProcessAdminUser()).isFalse(); + } + + @Test + public void testAssignAdminPrivileges() { + int userId = 30; + UserInfo testInfo = createUserInfoForId(userId); + + // Test that non-admins cannot assign admin privileges. + doReturn(false).when(mUserManager).isAdminUser(); // Current user non-admin. + mCarUserManagerHelper.assignAdminPrivileges(testInfo); + verify(mUserManager, never()).setUserAdmin(userId); + + // Admins can assign admin privileges. + doReturn(true).when(mUserManager).isAdminUser(); + mCarUserManagerHelper.assignAdminPrivileges(testInfo); + verify(mUserManager).setUserAdmin(userId); + } + + @Test + public void testSetUserRestriction() { + int userId = 20; + UserInfo testInfo = createUserInfoForId(userId); + + mCarUserManagerHelper.setUserRestriction( + testInfo, UserManager.DISALLOW_ADD_USER, /* enable= */ true); + verify(mUserManager).setUserRestriction( + UserManager.DISALLOW_ADD_USER, true, UserHandle.of(userId)); + + mCarUserManagerHelper.setUserRestriction( + testInfo, UserManager.DISALLOW_REMOVE_USER, /* enable= */ false); + verify(mUserManager).setUserRestriction( + UserManager.DISALLOW_REMOVE_USER, false, UserHandle.of(userId)); + } + + @Test + public void testDefaultNonAdminRestrictions() { + String testUserName = "Test User"; + int userId = 20; + UserInfo newNonAdmin = createUserInfoForId(userId); + + doReturn(newNonAdmin).when(mUserManager).createUser(testUserName, /* flags= */ 0); + + mCarUserManagerHelper.createNewNonAdminUser(testUserName); + + verify(mUserManager).setUserRestriction( + UserManager.DISALLOW_FACTORY_RESET, /* enable= */ true, UserHandle.of(userId)); + verify(mUserManager).setUserRestriction( + UserManager.DISALLOW_SMS, /* enable= */ false, UserHandle.of(userId)); + verify(mUserManager).setUserRestriction( + UserManager.DISALLOW_OUTGOING_CALLS, /* enable= */ false, UserHandle.of(userId)); + } + + @Test + public void testDefaultGuestRestrictions() { + int guestRestrictionsExpectedCount = 7; + + ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); + mCarUserManagerHelper.initDefaultGuestRestrictions(); + + verify(mUserManager).setDefaultGuestRestrictions(bundleCaptor.capture()); + Bundle guestRestrictions = bundleCaptor.getValue(); + + assertThat(guestRestrictions.keySet()).hasSize(guestRestrictionsExpectedCount); + assertThat(guestRestrictions.getBoolean(UserManager.DISALLOW_FACTORY_RESET)).isTrue(); + assertThat(guestRestrictions.getBoolean(UserManager.DISALLOW_REMOVE_USER)).isTrue(); + assertThat(guestRestrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)).isTrue(); + assertThat(guestRestrictions.getBoolean(UserManager.DISALLOW_OUTGOING_CALLS)).isTrue(); + assertThat(guestRestrictions.getBoolean(UserManager.DISALLOW_SMS)).isTrue(); + assertThat(guestRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_APPS)).isTrue(); + assertThat(guestRestrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS)).isTrue(); + } + + @Test + public void testAssigningAdminPrivilegesRemovesNonAdminRestrictions() { + int testUserId = 30; + boolean restrictionEnabled = false; + UserInfo testInfo = createUserInfoForId(testUserId); + + // Only admins can assign privileges. + doReturn(true).when(mUserManager).isAdminUser(); + + mCarUserManagerHelper.assignAdminPrivileges(testInfo); + + verify(mUserManager).setUserRestriction( + UserManager.DISALLOW_FACTORY_RESET, restrictionEnabled, UserHandle.of(testUserId)); + } + + @Test public void testRegisterUserChangeReceiver() { - mHelper.registerOnUsersUpdateListener(mTestListener); + mCarUserManagerHelper.registerOnUsersUpdateListener(mTestListener); ArgumentCaptor<BroadcastReceiver> receiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); @@ -375,13 +641,148 @@ public class CarUserManagerHelperTest { assertThat(handlerCaptor.getValue()).isNull(); // Unregister the receiver. - mHelper.unregisterOnUsersUpdateListener(); + mCarUserManagerHelper.unregisterOnUsersUpdateListener(mTestListener); verify(mContext).unregisterReceiver(receiverCaptor.getValue()); } + @Test + public void testMultipleRegistrationsOfSameListener() { + CarUserManagerHelper.OnUsersUpdateListener listener = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + + ArgumentCaptor<BroadcastReceiver> receiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + + mCarUserManagerHelper.registerOnUsersUpdateListener(listener); + mCarUserManagerHelper.registerOnUsersUpdateListener(listener); + // Even for multiple registrations of the same listener, broadcast receiver registered once. + verify(mContext, times(1)) + .registerReceiverAsUser(receiverCaptor.capture(), any(), any(), any(), any()); + + // Verify that calling the receiver calls the listener. + receiverCaptor.getValue().onReceive(mContext, new Intent()); + verify(listener).onUsersUpdate(); + + // Verify that a single removal unregisters the listener. + mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener); + verify(mContext).unregisterReceiver(any()); + } + + @Test + public void testMultipleUnregistrationsOfTheSameListener() { + CarUserManagerHelper.OnUsersUpdateListener listener = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + mCarUserManagerHelper.registerOnUsersUpdateListener(listener); + + // Verify that a multiple unregistrations cause only one unregister for broadcast receiver. + mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener); + mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener); + mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener); + verify(mContext, times(1)).unregisterReceiver(any()); + } + + @Test + public void testUnregisterReceiverCalledAfterAllListenersUnregister() { + CarUserManagerHelper.OnUsersUpdateListener listener1 = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + CarUserManagerHelper.OnUsersUpdateListener listener2 = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + + mCarUserManagerHelper.registerOnUsersUpdateListener(listener1); + mCarUserManagerHelper.registerOnUsersUpdateListener(listener2); + + mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener1); + verify(mContext, never()).unregisterReceiver(any()); + + mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener2); + verify(mContext, times(1)).unregisterReceiver(any()); + } + + @Test + public void testRegisteringMultipleListeners() { + CarUserManagerHelper.OnUsersUpdateListener listener1 = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + CarUserManagerHelper.OnUsersUpdateListener listener2 = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + ArgumentCaptor<BroadcastReceiver> receiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + + mCarUserManagerHelper.registerOnUsersUpdateListener(listener1); + mCarUserManagerHelper.registerOnUsersUpdateListener(listener2); + verify(mContext, times(1)) + .registerReceiverAsUser(receiverCaptor.capture(), any(), any(), any(), any()); + + // Verify that calling the receiver calls both listeners. + receiverCaptor.getValue().onReceive(mContext, new Intent()); + verify(listener1).onUsersUpdate(); + verify(listener2).onUsersUpdate(); + } + + @Test + public void testUnregisteringListenerStopsUpdatesForListener() { + CarUserManagerHelper.OnUsersUpdateListener listener1 = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + CarUserManagerHelper.OnUsersUpdateListener listener2 = + Mockito.mock(CarUserManagerHelper.OnUsersUpdateListener.class); + ArgumentCaptor<BroadcastReceiver> receiverCaptor = + ArgumentCaptor.forClass(BroadcastReceiver.class); + + mCarUserManagerHelper.registerOnUsersUpdateListener(listener1); + mCarUserManagerHelper.registerOnUsersUpdateListener(listener2); + verify(mContext, times(1)) + .registerReceiverAsUser(receiverCaptor.capture(), any(), any(), any(), any()); + + // Unregister listener2 + mCarUserManagerHelper.unregisterOnUsersUpdateListener(listener2); + + // Verify that calling the receiver calls only one listener. + receiverCaptor.getValue().onReceive(mContext, new Intent()); + verify(listener1).onUsersUpdate(); + verify(listener2, never()).onUsersUpdate(); + } + + @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); + + mCarUserManagerHelper.setLastActiveUser( + lastActiveUserId, /* skipGlobalSettings= */ true); + mockGetUsers(mSystemUser, otherUser1, otherUser2, otherUser3); + + 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); + + mCarUserManagerHelper.setLastActiveUser( + lastActiveUserId, /* skipGlobalSettings= */ true); + mockGetUsers(mSystemUser, otherUser1, otherUser2); + + assertThat(mCarUserManagerHelper.getInitialUser()).isEqualTo(lastActiveUserId - 2); + } + private UserInfo createUserInfoForId(int id) { UserInfo userInfo = new UserInfo(); userInfo.id = id; return userInfo; } + + private void mockGetUsers(UserInfo... users) { + List<UserInfo> testUsers = new ArrayList<>(); + for (UserInfo user: users) { + testUsers.add(user); + } + doReturn(testUsers).when(mUserManager).getUsers(true); + } } 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 faa7bd0965..48d447bc0f 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 @@ -21,18 +21,17 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.car.user.CarUserManagerHelper; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.UserInfo; +import android.location.LocationManager; +import android.os.UserHandle; +import android.os.UserManager; import android.support.test.runner.AndroidJUnit4; -import java.util.ArrayList; -import java.util.List; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,6 +39,9 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.List; + /** * This class contains unit tests for the {@link CarUserService}. * @@ -60,17 +62,23 @@ public class CarUserServiceTest { private Context mApplicationContext; @Mock + private LocationManager mLocationManager; + + @Mock private CarUserManagerHelper mCarUserManagerHelper; /** * Initialize all of the objects with the @Mock annotation. */ @Before - public void setUp() throws Exception { + public void setUpMocks() throws Exception { MockitoAnnotations.initMocks(this); - when(mMockContext.getApplicationContext()).thenReturn(mApplicationContext); + doReturn(mApplicationContext).when(mMockContext).getApplicationContext(); + doReturn(mLocationManager).when(mMockContext).getSystemService(Context.LOCATION_SERVICE); mCarUserService = new CarUserService(mMockContext, mCarUserManagerHelper); + + doReturn(new ArrayList<>()).when(mCarUserManagerHelper).getAllUsers(); } /** @@ -83,9 +91,10 @@ public class CarUserServiceTest { 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); } /** @@ -102,20 +111,123 @@ public class CarUserServiceTest { */ @Test public void testStartsSecondaryAdminUserOnFirstRun() { + UserInfo admin = mockAdmin(/* adminId= */ 10); + + mCarUserService.onReceive(mMockContext, + new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)); + + verify(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME); + verify(mCarUserManagerHelper).switchToUser(admin); + } + + /** + * Test that the {@link CarUserService} disable modify account for user 0 upon first run. + */ + @Test + public void testDisableModifyAccountsForSystemUserOnFirstRun() { + // Mock system user. + UserInfo systemUser = new UserInfo(); + systemUser.id = UserHandle.USER_SYSTEM; + doReturn(systemUser).when(mCarUserManagerHelper).getSystemUserInfo(); + + mockAdmin(10); + + mCarUserService.onReceive(mMockContext, + new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)); + + verify(mCarUserManagerHelper) + .setUserRestriction(systemUser, UserManager.DISALLOW_MODIFY_ACCOUNTS, true); + } + + /** + * Test that the {@link CarUserService} disable location service for user 0 upon first run. + */ + @Test + public void testDisableLocationForSystemUserOnFirstRun() { + mockAdmin(/* adminId= */ 10); + + mCarUserService.onReceive(mMockContext, + new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)); + + verify(mLocationManager).setLocationEnabledForUser( + /* enabled= */ false, UserHandle.of(UserHandle.USER_SYSTEM)); + } + + /** + * Test that the {@link CarUserService} updates last active user to the first admin user + * on first run. + */ + @Test + public void testUpdateLastActiveUserOnFirstRun() { + UserInfo admin = mockAdmin(/* adminId= */ 10); + + mCarUserService.onReceive(mMockContext, + new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)); + + verify(mCarUserManagerHelper) + .setLastActiveUser(admin.id, /* skipGlobalSetting= */ false); + } + + /** + * 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(users).when(mCarUserManagerHelper.getAllUsers()); - doReturn(admin).when(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME); - doReturn(true).when(mCarUserManagerHelper).switchToUser(admin); + doReturn(secUserId).when(mCarUserManagerHelper).getInitialUser(); mCarUserService.onReceive(mMockContext, new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)); - verify(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME); - verify(mCarUserManagerHelper).switchToUser(admin); + verify(mCarUserManagerHelper).switchToUserId(secUserId); + } + + /** + * Test that the {@link CarUserService} updates last active user on user switch intent. + */ + @Test + public void testLastActiveUserUpdatedOnUserSwitch() { + int lastActiveUserId = 11; + + Intent intent = new Intent(Intent.ACTION_USER_SWITCHED); + intent.putExtra(Intent.EXTRA_USER_HANDLE, lastActiveUserId); + + doReturn(true).when(mCarUserManagerHelper).isPersistentUser(lastActiveUserId); + + mCarUserService.onReceive(mMockContext, intent); + + verify(mCarUserManagerHelper).setLastActiveUser( + lastActiveUserId, /* skipGlobalSetting= */ false); + } + + /** + * Test that the {@link CarUserService} sets default guest restrictions on first boot. + */ + @Test + public void testInitializeGuestRestrictionsOnFirstRun() { + mockAdmin(/* adminId= */ 10); + + mCarUserService.onReceive(mMockContext, + new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)); + + verify(mCarUserManagerHelper).initDefaultGuestRestrictions(); + } + + private UserInfo mockAdmin(int adminId) { + UserInfo admin = new UserInfo(adminId, CarUserService.OWNER_NAME, UserInfo.FLAG_ADMIN); + doReturn(admin).when(mCarUserManagerHelper).createNewAdminUser(CarUserService.OWNER_NAME); + return admin; } } |