1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.car.user; 17 18 import static android.car.test.mock.CarMockitoHelper.mockHandleRemoteExceptionFromCarServiceWithDefaultValue; 19 import static android.car.test.util.CarTestingHelper.getResult; 20 import static android.os.UserHandle.SYSTEM; 21 import static android.os.UserHandle.USER_SYSTEM; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.junit.Assert.assertThrows; 26 import static org.mockito.ArgumentMatchers.any; 27 import static org.mockito.ArgumentMatchers.anyBoolean; 28 import static org.mockito.ArgumentMatchers.anyInt; 29 import static org.mockito.ArgumentMatchers.eq; 30 import static org.mockito.ArgumentMatchers.isNull; 31 import static org.mockito.ArgumentMatchers.notNull; 32 import static org.mockito.ArgumentMatchers.same; 33 import static org.mockito.Mockito.doAnswer; 34 import static org.mockito.Mockito.doThrow; 35 import static org.mockito.Mockito.times; 36 import static org.mockito.Mockito.verify; 37 import static org.mockito.Mockito.when; 38 39 import android.annotation.NonNull; 40 import android.annotation.Nullable; 41 import android.annotation.UserIdInt; 42 import android.car.ICarUserService; 43 import android.car.SyncResultCallback; 44 import android.car.test.AbstractExpectableTestCase; 45 import android.car.test.util.UserTestingHelper; 46 import android.car.user.CarUserManager.UserHandleSwitchUiCallback; 47 import android.car.user.CarUserManager.UserLifecycleListener; 48 import android.car.user.CarUserManager.UserSwitchUiCallback; 49 import android.car.util.concurrent.AndroidFuture; 50 import android.car.util.concurrent.AsyncFuture; 51 import android.content.Context; 52 import android.content.pm.UserInfo; 53 import android.content.pm.UserInfo.UserInfoFlag; 54 import android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue; 55 import android.hardware.automotive.vehicle.UserIdentificationAssociationType; 56 import android.hardware.automotive.vehicle.UserIdentificationAssociationValue; 57 import android.os.RemoteException; 58 import android.os.UserHandle; 59 import android.os.UserManager; 60 import android.platform.test.ravenwood.RavenwoodRule; 61 62 import com.android.car.internal.ICarBase; 63 import com.android.car.internal.ResultCallbackImpl; 64 65 import org.junit.Before; 66 import org.junit.Rule; 67 import org.junit.Test; 68 import org.junit.runner.RunWith; 69 import org.mockito.Mock; 70 import org.mockito.junit.MockitoJUnitRunner; 71 72 import java.util.Arrays; 73 import java.util.List; 74 import java.util.stream.Collectors; 75 76 @RunWith(MockitoJUnitRunner.class) 77 public final class CarUserManagerUnitTest extends AbstractExpectableTestCase { 78 79 // Need to a rule to setup host implementation for SystemProperties.get which is used inside 80 // CarSystemProperties.getUserHalTimeout() during CarUserManager initialization. 81 @Rule 82 public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder() 83 .setSystemPropertyImmutable("android.car.user_hal_timeout", "") 84 // AndroidFuture uses getMainHandler 85 .setProvideMainThread(true) 86 .build(); 87 88 @Mock 89 private ICarBase mCar; 90 @Mock 91 private UserManager mUserManager; 92 @Mock 93 private ICarUserService mService; 94 @Mock 95 private Context mMockContext; 96 97 private CarUserManager mMgr; 98 99 @Before setFixtures()100 public void setFixtures() { 101 mMgr = new CarUserManager(mCar, mService, mUserManager, 102 /* isHeadlessSystemUserMode= */ true); 103 when(mCar.getContext()).thenReturn(mMockContext); 104 } 105 106 @Test testUserIdentificationAssociationType()107 public void testUserIdentificationAssociationType() { 108 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_TYPE_KEY_FOB) 109 .isEqualTo(UserIdentificationAssociationType.KEY_FOB); 110 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_1) 111 .isEqualTo(UserIdentificationAssociationType.CUSTOM_1); 112 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_2) 113 .isEqualTo(UserIdentificationAssociationType.CUSTOM_2); 114 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_3) 115 .isEqualTo(UserIdentificationAssociationType.CUSTOM_3); 116 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_4) 117 .isEqualTo(UserIdentificationAssociationType.CUSTOM_4); 118 } 119 120 @Test testUserIdentificationAssociationSetValue()121 public void testUserIdentificationAssociationSetValue() { 122 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_ASSOCIATE_CURRENT_USER) 123 .isEqualTo(UserIdentificationAssociationSetValue.ASSOCIATE_CURRENT_USER); 124 assertThat( 125 CarUserManager.USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_CURRENT_USER) 126 .isEqualTo(UserIdentificationAssociationSetValue.DISASSOCIATE_CURRENT_USER); 127 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_ALL_USERS) 128 .isEqualTo(UserIdentificationAssociationSetValue.DISASSOCIATE_ALL_USERS); 129 } 130 131 @Test testUserIdentificationAssociationValue()132 public void testUserIdentificationAssociationValue() { 133 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_VALUE_UNKNOWN) 134 .isEqualTo(UserIdentificationAssociationValue.UNKNOWN); 135 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATE_CURRENT_USER) 136 .isEqualTo(UserIdentificationAssociationValue.ASSOCIATED_CURRENT_USER); 137 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATED_ANOTHER_USER) 138 .isEqualTo(UserIdentificationAssociationValue.ASSOCIATED_ANOTHER_USER); 139 assertThat(CarUserManager.USER_IDENTIFICATION_ASSOCIATION_VALUE_NOT_ASSOCIATED_ANY_USER) 140 .isEqualTo(UserIdentificationAssociationValue.NOT_ASSOCIATED_ANY_USER); 141 } 142 143 @Test testIsValidUserId_headlessSystemUser()144 public void testIsValidUserId_headlessSystemUser() { 145 setExistingUsers(USER_SYSTEM); 146 147 assertThat(mMgr.isValidUser(USER_SYSTEM)).isFalse(); 148 } 149 150 @Test testIsValidUser_headlessSystemUser()151 public void testIsValidUser_headlessSystemUser() { 152 setExistingUsers(USER_SYSTEM); 153 154 assertThat(mMgr.isValidUser(SYSTEM)).isFalse(); 155 } 156 157 @Test testIsValidUserId_nonHeadlessSystemUser()158 public void testIsValidUserId_nonHeadlessSystemUser() { 159 mockIsHeadlessSystemUserMode(false); 160 setExistingUsers(USER_SYSTEM); 161 162 assertThat(mMgr.isValidUser(USER_SYSTEM)).isTrue(); 163 } 164 165 @Test testIsValidUser_nonHeadlessSystemUser()166 public void testIsValidUser_nonHeadlessSystemUser() { 167 mockIsHeadlessSystemUserMode(false); 168 setExistingUsers(USER_SYSTEM); 169 170 assertThat(mMgr.isValidUser(SYSTEM)).isTrue(); 171 } 172 173 @Test testIsValidUserId_found()174 public void testIsValidUserId_found() { 175 setExistingUsers(1, 2, 3); 176 177 expectThat(mMgr.isValidUser(1)).isTrue(); 178 expectThat(mMgr.isValidUser(2)).isTrue(); 179 expectThat(mMgr.isValidUser(3)).isTrue(); 180 } 181 182 @Test testIsValidUser_found()183 public void testIsValidUser_found() { 184 setExistingUsers(1, 2, 3); 185 186 expectThat(mMgr.isValidUser(UserHandle.of(1))).isTrue(); 187 expectThat(mMgr.isValidUser(UserHandle.of(2))).isTrue(); 188 expectThat(mMgr.isValidUser(UserHandle.of(3))).isTrue(); 189 } 190 191 @Test testIsValidUserId_notFound()192 public void testIsValidUserId_notFound() { 193 setExistingUsers(1, 2, 3); 194 195 assertThat(mMgr.isValidUser(4)).isFalse(); 196 } 197 198 @Test testIsValidUser_notFound()199 public void testIsValidUser_notFound() { 200 setExistingUsers(1, 2, 3); 201 202 assertThat(mMgr.isValidUser(UserHandle.of(4))).isFalse(); 203 } 204 205 @Test testIsValidUserId_emptyUsers()206 public void testIsValidUserId_emptyUsers() { 207 assertThat(mMgr.isValidUser(666)).isFalse(); 208 } 209 210 @Test testIsValidUser_emptyUsers()211 public void testIsValidUser_emptyUsers() { 212 assertThat(mMgr.isValidUser(UserHandle.of(666))).isFalse(); 213 } 214 215 @Test testAddListener_nullExecutor()216 public void testAddListener_nullExecutor() { 217 assertThrows(NullPointerException.class, () -> mMgr.addListener(null, (e) -> { })); 218 } 219 220 @Test testAddListener_nullListener()221 public void testAddListener_nullListener() { 222 assertThrows(NullPointerException.class, () -> mMgr.addListener(Runnable::run, null)); 223 } 224 225 @Test testAddListener_nullFilter()226 public void testAddListener_nullFilter() { 227 assertThrows(NullPointerException.class, 228 () -> mMgr.addListener(Runnable::run, /* filter= */null, (e) -> {})); 229 } 230 231 @Test testAddListener_sameListenerAddedTwice()232 public void testAddListener_sameListenerAddedTwice() { 233 UserLifecycleListener listener = (e) -> { }; 234 235 mMgr.addListener(Runnable::run, listener); 236 assertThrows(IllegalStateException.class, () -> mMgr.addListener(Runnable::run, listener)); 237 } 238 239 @Test testAddListener_differentListenersAddedTwice()240 public void testAddListener_differentListenersAddedTwice() throws Exception { 241 mMgr.addListener(Runnable::run, (e) -> { }); 242 mMgr.addListener(Runnable::run, (e) -> { }); 243 244 verify(mService, times(2)).setLifecycleListenerForApp(any(), isNull(), any()); 245 } 246 247 @Test testAddListener_differentListenersWithFilter()248 public void testAddListener_differentListenersWithFilter() throws Exception { 249 UserLifecycleEventFilter filter1 = new UserLifecycleEventFilter.Builder() 250 .addEventType(CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING).build(); 251 mMgr.addListener(Runnable::run, filter1, (e) -> { }); 252 UserLifecycleEventFilter filter2 = new UserLifecycleEventFilter.Builder() 253 .addUser(UserHandle.CURRENT).build(); 254 mMgr.addListener(Runnable::run, filter2, (e) -> { }); 255 256 verify(mService).setLifecycleListenerForApp(any(), eq(filter1), any()); 257 verify(mService).setLifecycleListenerForApp(any(), eq(filter2), any()); 258 } 259 260 @Test testRemoveListener_nullListener()261 public void testRemoveListener_nullListener() { 262 assertThrows(NullPointerException.class, () -> mMgr.removeListener(null)); 263 } 264 265 @Test testRemoveListener_notAddedBefore()266 public void testRemoveListener_notAddedBefore() { 267 UserLifecycleListener listener = (e) -> { }; 268 269 assertThrows(IllegalStateException.class, () -> mMgr.removeListener(listener)); 270 } 271 272 @Test testRemoveListener_addAndRemove()273 public void testRemoveListener_addAndRemove() { 274 UserLifecycleListener listener = (e) -> { }; 275 276 mMgr.addListener(Runnable::run, listener); 277 mMgr.removeListener(listener); 278 279 // Make sure it was removed 280 assertThrows(IllegalStateException.class, () -> mMgr.removeListener(listener)); 281 } 282 283 @Test testSwitchUser_success()284 public void testSwitchUser_success() throws Exception { 285 expectServiceSwitchUserSucceeds(11, UserSwitchResult.STATUS_SUCCESSFUL); 286 287 mMgr.switchUser(new UserSwitchRequest.Builder( 288 UserHandle.of(11)).build(), Runnable::run, response -> { 289 assertThat(response.getStatus()).isEqualTo(UserSwitchResult.STATUS_SUCCESSFUL); 290 assertThat(response.getErrorMessage()).isNull(); 291 } 292 ); 293 294 } 295 296 @Test testSwitchUserId_success()297 public void testSwitchUserId_success() throws Exception { 298 expectServiceSwitchUserSucceeds(11, UserSwitchResult.STATUS_SUCCESSFUL); 299 300 AsyncFuture<UserSwitchResult> future = mMgr.switchUser(11); 301 302 assertThat(future).isNotNull(); 303 UserSwitchResult result = getResult(future); 304 assertThat(result.getStatus()).isEqualTo(UserSwitchResult.STATUS_SUCCESSFUL); 305 assertThat(result.getErrorMessage()).isNull(); 306 } 307 308 @Test testSwitchUser_remoteException()309 public void testSwitchUser_remoteException() throws Exception { 310 expectServiceSwitchUserFails(11, new RemoteException("D'OH!")); 311 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 312 313 mMgr.switchUser(new UserSwitchRequest.Builder( 314 UserHandle.of(11)).build(), Runnable::run, response -> { 315 assertThat(response.getStatus()).isEqualTo( 316 UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 317 assertThat(response.getErrorMessage()).isNull(); 318 } 319 ); 320 } 321 322 @Test testSwitchUserId_remoteException()323 public void testSwitchUserId_remoteException() throws Exception { 324 expectServiceSwitchUserFails(11, new RemoteException("D'OH!")); 325 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 326 327 AsyncFuture<UserSwitchResult> future = mMgr.switchUser(11); 328 329 assertThat(future).isNotNull(); 330 UserSwitchResult result = getResult(future); 331 assertThat(result.getStatus()).isEqualTo(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 332 assertThat(result.getErrorMessage()).isNull(); 333 } 334 335 @Test testSwitchUser_runtimeException()336 public void testSwitchUser_runtimeException() throws Exception { 337 expectServiceSwitchUserFails(11, new RuntimeException("D'OH!")); 338 339 mMgr.switchUser(new UserSwitchRequest.Builder( 340 UserHandle.of(11)).build(), Runnable::run, response -> { 341 assertThat(response.getStatus()).isEqualTo( 342 UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 343 assertThat(response.getErrorMessage()).isNull(); 344 } 345 ); 346 } 347 348 @Test testSwitchUserId_runtimeException()349 public void testSwitchUserId_runtimeException() throws Exception { 350 expectServiceSwitchUserFails(11, new RuntimeException("D'OH!")); 351 352 AsyncFuture<UserSwitchResult> future = mMgr.switchUser(11); 353 354 assertThat(future).isNotNull(); 355 UserSwitchResult result = getResult(future); 356 assertThat(result.getStatus()).isEqualTo(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 357 assertThat(result.getErrorMessage()).isNull(); 358 } 359 360 @Test testLogoutUser_success()361 public void testLogoutUser_success() throws Exception { 362 expectServiceLogoutUserSucceeds(UserSwitchResult.STATUS_SUCCESSFUL); 363 364 AsyncFuture<UserSwitchResult> future = mMgr.logoutUser(); 365 366 assertThat(future).isNotNull(); 367 UserSwitchResult result = getResult(future); 368 assertThat(result.getStatus()).isEqualTo(UserSwitchResult.STATUS_SUCCESSFUL); 369 assertThat(result.getErrorMessage()).isNull(); 370 } 371 372 @Test testLogoutUser_remoteException()373 public void testLogoutUser_remoteException() throws Exception { 374 expectServiceLogoutUserFails(new RemoteException("D'OH!")); 375 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 376 377 AsyncFuture<UserSwitchResult> future = mMgr.logoutUser(); 378 379 assertThat(future).isNotNull(); 380 UserSwitchResult result = getResult(future); 381 assertThat(result.getStatus()).isEqualTo(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 382 assertThat(result.getErrorMessage()).isNull(); 383 } 384 385 @Test testLogoutUser_runtimeException()386 public void testLogoutUser_runtimeException() throws Exception { 387 expectServiceLogoutUserFails(new RuntimeException("D'OH!")); 388 389 AsyncFuture<UserSwitchResult> future = mMgr.logoutUser(); 390 391 assertThat(future).isNotNull(); 392 UserSwitchResult result = getResult(future); 393 assertThat(result.getStatus()).isEqualTo(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 394 assertThat(result.getErrorMessage()).isNull(); 395 } 396 397 @Test testRemoveUser_success()398 public void testRemoveUser_success() throws Exception { 399 expectServiceRemoveUserSucceeds(100); 400 401 mMgr.removeUser(new UserRemovalRequest.Builder( 402 UserHandle.of(100)).build(), Runnable::run, response -> 403 assertThat(response.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL) 404 ); 405 } 406 407 @Test testRemoveUserId_success()408 public void testRemoveUserId_success() throws Exception { 409 expectServiceRemoveUserSucceeds(100); 410 411 UserRemovalResult result = mMgr.removeUser(100); 412 413 assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_SUCCESSFUL); 414 } 415 416 @Test testRemoveUser_remoteException()417 public void testRemoveUser_remoteException() throws Exception { 418 doThrow(new RemoteException("D'OH!")).when(mService).removeUser(eq(100), any()); 419 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 420 421 mMgr.removeUser(new UserRemovalRequest.Builder( 422 UserHandle.of(100)).build(), Runnable::run, response -> 423 assertThat(response.getStatus()).isEqualTo(UserRemovalResult.STATUS_ANDROID_FAILURE) 424 ); 425 } 426 427 @Test testRemoveUserId_remoteException()428 public void testRemoveUserId_remoteException() throws Exception { 429 doThrow(new RemoteException("D'OH!")).when(mService).removeUser(eq(100), any()); 430 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 431 432 UserRemovalResult result = mMgr.removeUser(100); 433 434 assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_ANDROID_FAILURE); 435 } 436 437 @Test testRemoveUser_runtimeException()438 public void testRemoveUser_runtimeException() throws Exception { 439 doThrow(new RuntimeException("D'OH!")).when(mService).removeUser(eq(100), any()); 440 441 mMgr.removeUser(new UserRemovalRequest.Builder( 442 UserHandle.of(100)).build(), Runnable::run, response -> 443 assertThat(response.getStatus()).isEqualTo(UserRemovalResult.STATUS_ANDROID_FAILURE) 444 ); 445 } 446 447 @Test testRemoveUserId_runtimeException()448 public void testRemoveUserId_runtimeException() throws Exception { 449 doThrow(new RuntimeException("D'OH!")).when(mService).removeUser(eq(100), any()); 450 451 UserRemovalResult result = mMgr.removeUser(100); 452 453 assertThat(result.getStatus()).isEqualTo(UserRemovalResult.STATUS_ANDROID_FAILURE); 454 } 455 456 @Test testSetSwitchUserIdUICallback_success()457 public void testSetSwitchUserIdUICallback_success() throws Exception { 458 UserSwitchUiCallback callback = (u)-> {}; 459 460 mMgr.setUserSwitchUiCallback(callback); 461 462 verify(mService).setUserSwitchUiCallback(any()); 463 } 464 465 @Test testSetSwitchUserUICallback_nullCallback()466 public void testSetSwitchUserUICallback_nullCallback() throws Exception { 467 assertThrows(IllegalArgumentException.class, () -> mMgr.setUserSwitchUiCallback(null)); 468 } 469 470 @Test testSetSwitchUserUICallback_success()471 public void testSetSwitchUserUICallback_success() throws Exception { 472 UserHandleSwitchUiCallback callback = (u)-> {}; 473 474 mMgr.setUserSwitchUiCallback(Runnable::run, callback); 475 476 verify(mService).setUserSwitchUiCallback(any()); 477 } 478 479 @Test testCreateUser_success()480 public void testCreateUser_success() throws Exception { 481 expectServiceCreateUserSucceeds("dude", UserManager.USER_TYPE_FULL_SECONDARY, 42, 482 UserCreationResult.STATUS_SUCCESSFUL); 483 SyncResultCallback<UserCreationResult> userCreationResultCallback = 484 new SyncResultCallback<>(); 485 486 mMgr.createUser(new UserCreationRequest.Builder().setName("dude").build(), Runnable::run, 487 userCreationResultCallback); 488 489 UserCreationResult result = userCreationResultCallback.get(); 490 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_SUCCESSFUL); 491 assertThat(result.isSuccess()).isTrue(); 492 assertThat(result.getErrorMessage()).isNull(); 493 494 UserHandle newUser = result.getUser(); 495 assertThat(newUser).isNotNull(); 496 assertThat(newUser.getIdentifier()).isEqualTo(108); 497 } 498 499 @Test testCreateUserId_success()500 public void testCreateUserId_success() throws Exception { 501 expectServiceCreateUserSucceeds("dude", UserManager.USER_TYPE_FULL_SECONDARY, 42, 502 UserCreationResult.STATUS_SUCCESSFUL); 503 504 AsyncFuture<UserCreationResult> future = mMgr.createUser("dude", 42); 505 assertThat(future).isNotNull(); 506 507 UserCreationResult result = getResult(future); 508 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_SUCCESSFUL); 509 assertThat(result.isSuccess()).isTrue(); 510 assertThat(result.getErrorMessage()).isNull(); 511 512 UserHandle newUser = result.getUser(); 513 assertThat(newUser).isNotNull(); 514 assertThat(newUser.getIdentifier()).isEqualTo(108); 515 } 516 517 @Test testCreateUser_remoteException()518 public void testCreateUser_remoteException() throws Exception { 519 expectServiceCreateUserFails(); 520 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 521 SyncResultCallback<UserCreationResult> userCreationResultCallback = 522 new SyncResultCallback<>(); 523 524 mMgr.createUser(new UserCreationRequest.Builder().setName("dude").build(), Runnable::run, 525 userCreationResultCallback); 526 527 UserCreationResult result = userCreationResultCallback.get(); 528 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE); 529 assertThat(result.isSuccess()).isFalse(); 530 assertThat(result.getErrorMessage()).isNull(); 531 assertThat(result.getUser()).isNull(); 532 } 533 534 @Test testCreateUserId_remoteException()535 public void testCreateUserId_remoteException() throws Exception { 536 expectServiceCreateUserFails(); 537 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 538 539 AsyncFuture<UserCreationResult> future = mMgr.createUser("dude", 42); 540 assertThat(future).isNotNull(); 541 542 UserCreationResult result = getResult(future); 543 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE); 544 assertThat(result.isSuccess()).isFalse(); 545 assertThat(result.getErrorMessage()).isNull(); 546 assertThat(result.getUser()).isNull(); 547 } 548 549 @Test testCreateUser_runtimeException()550 public void testCreateUser_runtimeException() throws Exception { 551 doThrow(new RuntimeException("D'OH!")).when(mService).createUser(notNull(), anyInt(), 552 notNull()); 553 SyncResultCallback<UserCreationResult> userCreationResultCallback = 554 new SyncResultCallback<>(); 555 556 mMgr.createUser(new UserCreationRequest.Builder().setName("dude").build(), Runnable::run, 557 userCreationResultCallback); 558 559 UserCreationResult result = userCreationResultCallback.get(); 560 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE); 561 assertThat(result.isSuccess()).isFalse(); 562 assertThat(result.getErrorMessage()).isNull(); 563 assertThat(result.getUser()).isNull(); 564 } 565 566 @Test testCreateUserId_runtimeException()567 public void testCreateUserId_runtimeException() throws Exception { 568 doThrow(new RuntimeException("D'OH!")).when(mService).createUser(notNull(), anyInt(), 569 notNull()); 570 571 AsyncFuture<UserCreationResult> future = mMgr.createUser("dude", 42); 572 assertThat(future).isNotNull(); 573 574 UserCreationResult result = getResult(future); 575 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE); 576 assertThat(result.isSuccess()).isFalse(); 577 assertThat(result.getErrorMessage()).isNull(); 578 assertThat(result.getUser()).isNull(); 579 } 580 581 @Test testCreateGuest_success()582 public void testCreateGuest_success() throws Exception { 583 expectServiceCreateUserSucceeds("dudeGuest", UserManager.USER_TYPE_FULL_GUEST, 0, 584 UserCreationResult.STATUS_SUCCESSFUL); 585 586 AsyncFuture<UserCreationResult> future = mMgr.createGuest("dudeGuest"); 587 assertThat(future).isNotNull(); 588 589 UserCreationResult result = getResult(future); 590 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_SUCCESSFUL); 591 assertThat(result.isSuccess()).isTrue(); 592 assertThat(result.getErrorMessage()).isNull(); 593 594 UserHandle newUser = result.getUser(); 595 assertThat(newUser).isNotNull(); 596 assertThat(newUser.getIdentifier()).isEqualTo(108); 597 } 598 599 @Test testCreateGuest_remoteException()600 public void testCreateGuest_remoteException() throws Exception { 601 expectServiceCreateUserFails(); 602 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 603 604 AsyncFuture<UserCreationResult> future = mMgr.createGuest("dudeGuest"); 605 assertThat(future).isNotNull(); 606 607 UserCreationResult result = getResult(future); 608 assertThat(result.getStatus()).isEqualTo(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE); 609 assertThat(result.isSuccess()).isFalse(); 610 assertThat(result.getErrorMessage()).isNull(); 611 assertThat(result.getUser()).isNull(); 612 } 613 614 @Test testGetUserIdentificationAssociation_nullTypes()615 public void testGetUserIdentificationAssociation_nullTypes() throws Exception { 616 assertThrows(IllegalArgumentException.class, 617 () -> mMgr.getUserIdentificationAssociation(null)); 618 } 619 620 @Test testGetUserIdentificationAssociation_emptyTypes()621 public void testGetUserIdentificationAssociation_emptyTypes() throws Exception { 622 assertThrows(IllegalArgumentException.class, 623 () -> mMgr.getUserIdentificationAssociation(new int[] {})); 624 } 625 626 @Test testGetUserIdentificationAssociation_remoteException()627 public void testGetUserIdentificationAssociation_remoteException() throws Exception { 628 int[] types = new int[] {1}; 629 when(mService.getUserIdentificationAssociation(types)) 630 .thenThrow(new RemoteException("D'OH!")); 631 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 632 633 UserIdentificationAssociationResponse response = 634 mMgr.getUserIdentificationAssociation(types); 635 636 assertThat(response).isNotNull(); 637 assertThat(response.isSuccess()).isFalse(); 638 } 639 640 @Test testGetUserIdentificationAssociation_runtimeException()641 public void testGetUserIdentificationAssociation_runtimeException() throws Exception { 642 int[] types = new int[] {1}; 643 when(mService.getUserIdentificationAssociation(types)) 644 .thenThrow(new RuntimeException("D'OH!")); 645 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 646 647 UserIdentificationAssociationResponse response = 648 mMgr.getUserIdentificationAssociation(types); 649 650 assertThat(response).isNotNull(); 651 assertThat(response.isSuccess()).isFalse(); 652 } 653 654 @Test testGetUserIdentificationAssociation_ok()655 public void testGetUserIdentificationAssociation_ok() throws Exception { 656 int[] types = new int[] { 4, 8, 15, 16, 23, 42 }; 657 UserIdentificationAssociationResponse expectedResponse = 658 UserIdentificationAssociationResponse.forSuccess(types); 659 when(mService.getUserIdentificationAssociation(types)).thenReturn(expectedResponse); 660 661 UserIdentificationAssociationResponse actualResponse = 662 mMgr.getUserIdentificationAssociation(types); 663 664 assertThat(actualResponse).isSameInstanceAs(expectedResponse); 665 } 666 667 @Test testSetUserIdentificationAssociation_nullTypes()668 public void testSetUserIdentificationAssociation_nullTypes() throws Exception { 669 assertThrows(IllegalArgumentException.class, 670 () -> mMgr.setUserIdentificationAssociation(null, new int[] {42})); 671 } 672 673 @Test testSetUserIdentificationAssociation_emptyTypes()674 public void testSetUserIdentificationAssociation_emptyTypes() throws Exception { 675 assertThrows(IllegalArgumentException.class, 676 () -> mMgr.setUserIdentificationAssociation(new int[0], new int[] {42})); 677 } 678 679 @Test testSetUserIdentificationAssociation_nullValues()680 public void testSetUserIdentificationAssociation_nullValues() throws Exception { 681 assertThrows(IllegalArgumentException.class, 682 () -> mMgr.setUserIdentificationAssociation(new int[] {42}, null)); 683 } 684 685 @Test testSetUserIdentificationAssociation_emptyValues()686 public void testSetUserIdentificationAssociation_emptyValues() throws Exception { 687 assertThrows(IllegalArgumentException.class, 688 () -> mMgr.setUserIdentificationAssociation(new int[] {42}, new int[0])); 689 } 690 691 @Test testSetUserIdentificationAssociation_sizeMismatch()692 public void testSetUserIdentificationAssociation_sizeMismatch() throws Exception { 693 assertThrows(IllegalArgumentException.class, 694 () -> mMgr.setUserIdentificationAssociation(new int[] {1}, new int[] {2, 3})); 695 } 696 697 @Test testSetUserIdentificationAssociation_remoteException()698 public void testSetUserIdentificationAssociation_remoteException() throws Exception { 699 int[] types = new int[] {1}; 700 int[] values = new int[] {2}; 701 doThrow(new RemoteException("D'OH!")).when(mService) 702 .setUserIdentificationAssociation(anyInt(), same(types), same(values), notNull()); 703 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 704 705 AsyncFuture<UserIdentificationAssociationResponse> future = 706 mMgr.setUserIdentificationAssociation(types, values); 707 708 assertThat(future).isNotNull(); 709 UserIdentificationAssociationResponse result = getResult(future); 710 assertThat(result.isSuccess()).isFalse(); 711 assertThat(result.getValues()).isNull(); 712 assertThat(result.getErrorMessage()).isNull(); 713 } 714 715 @Test testSetUserIdentificationAssociation_runtimeException()716 public void testSetUserIdentificationAssociation_runtimeException() throws Exception { 717 int[] types = new int[] {1}; 718 int[] values = new int[] {2}; 719 doThrow(new RuntimeException("D'OH!")).when(mService) 720 .setUserIdentificationAssociation(anyInt(), same(types), same(values), notNull()); 721 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 722 723 AsyncFuture<UserIdentificationAssociationResponse> future = 724 mMgr.setUserIdentificationAssociation(types, values); 725 726 assertThat(future).isNotNull(); 727 UserIdentificationAssociationResponse result = getResult(future); 728 assertThat(result.isSuccess()).isFalse(); 729 assertThat(result.getValues()).isNull(); 730 assertThat(result.getErrorMessage()).isNull(); 731 } 732 733 @Test testSetUserIdentificationAssociation_ok()734 public void testSetUserIdentificationAssociation_ok() throws Exception { 735 int[] types = new int[] { 1, 2, 3 }; 736 int[] values = new int[] { 10, 20, 30 }; 737 doAnswer((inv) -> { 738 @SuppressWarnings("unchecked") 739 AndroidFuture<UserIdentificationAssociationResponse> future = 740 (AndroidFuture<UserIdentificationAssociationResponse>) inv 741 .getArguments()[3]; 742 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse 743 .forSuccess(values, "D'OH!"); 744 future.complete(response); 745 return null; 746 }).when(mService) 747 .setUserIdentificationAssociation(anyInt(), same(types), same(values), notNull()); 748 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 749 750 AsyncFuture<UserIdentificationAssociationResponse> future = 751 mMgr.setUserIdentificationAssociation(types, values); 752 753 assertThat(future).isNotNull(); 754 UserIdentificationAssociationResponse result = getResult(future); 755 assertThat(result.isSuccess()).isTrue(); 756 assertThat(result.getValues()).asList().containsAtLeast(10, 20, 30).inOrder(); 757 assertThat(result.getErrorMessage()).isEqualTo("D'OH!"); 758 } 759 760 @Test testIsUserHalUserAssociation()761 public void testIsUserHalUserAssociation() throws Exception { 762 when(mService.isUserHalUserAssociationSupported()).thenReturn(false).thenReturn(true); 763 764 assertThat(mMgr.isUserHalUserAssociationSupported()).isFalse(); 765 assertThat(mMgr.isUserHalUserAssociationSupported()).isTrue(); 766 } 767 768 @Test testIsUserHalUserAssociation_remoteException()769 public void testIsUserHalUserAssociation_remoteException() throws Exception { 770 doThrow(new RemoteException("D'OH!")).when(mService).isUserHalUserAssociationSupported(); 771 mockHandleRemoteExceptionFromCarServiceWithDefaultValue(mCar); 772 773 assertThat(mMgr.isUserHalUserAssociationSupported()).isFalse(); 774 } 775 776 @Test testIsUserHalUserAssociation_runtimeException()777 public void testIsUserHalUserAssociation_runtimeException() throws Exception { 778 doThrow(new RuntimeException("D'OH!")).when(mService).isUserHalUserAssociationSupported(); 779 780 assertThat(mMgr.isUserHalUserAssociationSupported()).isFalse(); 781 } 782 expectServiceSwitchUserSucceeds(@serIdInt int userId, @UserSwitchResult.Status int status)783 private void expectServiceSwitchUserSucceeds(@UserIdInt int userId, 784 @UserSwitchResult.Status int status) throws RemoteException { 785 doAnswer((invocation) -> { 786 @SuppressWarnings("unchecked") 787 ResultCallbackImpl<UserSwitchResult> resultCallbackImpl = 788 (ResultCallbackImpl<UserSwitchResult>) invocation.getArguments()[2]; 789 resultCallbackImpl.complete(new UserSwitchResult(status, /* errorMessage= */ null)); 790 return null; 791 }).when(mService).switchUser(eq(userId), anyInt(), notNull(), anyBoolean()); 792 } 793 expectServiceSwitchUserFails(@serIdInt int userId, Exception e)794 private void expectServiceSwitchUserFails(@UserIdInt int userId, Exception e) throws Exception { 795 doThrow(e).when(mService).switchUser(eq(userId), anyInt(), notNull(), anyBoolean()); 796 } 797 expectServiceLogoutUserSucceeds(@serSwitchResult.Status int status)798 private void expectServiceLogoutUserSucceeds(@UserSwitchResult.Status int status) 799 throws RemoteException { 800 doAnswer((invocation) -> { 801 @SuppressWarnings("unchecked") 802 ResultCallbackImpl<UserSwitchResult> resultCallbackImpl = 803 (ResultCallbackImpl<UserSwitchResult>) invocation.getArguments()[1]; 804 resultCallbackImpl.complete(new UserSwitchResult(status, /* errorMessage= */ null)); 805 return null; 806 }).when(mService).logoutUser(anyInt(), notNull()); 807 } 808 expectServiceLogoutUserFails(Exception e)809 private void expectServiceLogoutUserFails(Exception e) throws Exception { 810 doThrow(e).when(mService).logoutUser(anyInt(), notNull()); 811 } 812 expectServiceRemoveUserSucceeds(@serIdInt int userId)813 private void expectServiceRemoveUserSucceeds(@UserIdInt int userId) throws RemoteException { 814 doAnswer((invocation) -> { 815 @SuppressWarnings("unchecked") 816 ResultCallbackImpl<UserRemovalResult> resultResultCallbackImpl = 817 (ResultCallbackImpl<UserRemovalResult>) invocation.getArguments()[1]; 818 resultResultCallbackImpl.complete( 819 new UserRemovalResult(UserRemovalResult.STATUS_SUCCESSFUL)); 820 return null; 821 }).when(mService).removeUser(eq(userId), notNull()); 822 } 823 expectServiceCreateUserSucceeds(@ullable String name, @NonNull String userType, @UserInfoFlag int flags, @UserCreationResult.Status int status)824 private void expectServiceCreateUserSucceeds(@Nullable String name, 825 @NonNull String userType, @UserInfoFlag int flags, 826 @UserCreationResult.Status int status) throws RemoteException { 827 doAnswer((invocation) -> { 828 @SuppressWarnings("unchecked") 829 UserInfo newUser = new UserTestingHelper.UserInfoBuilder(108) 830 .setName(name).setType(userType).setFlags(flags).build(); 831 ResultCallbackImpl<UserCreationResult> resultCallbackImpl = 832 (ResultCallbackImpl<UserCreationResult>) invocation.getArguments()[2]; 833 resultCallbackImpl.complete(new UserCreationResult(status, newUser.getUserHandle())); 834 return null; 835 }).when(mService).createUser(notNull(), anyInt(), notNull()); 836 } 837 expectServiceCreateUserFails()838 private void expectServiceCreateUserFails() throws RemoteException { 839 doThrow(new RemoteException("D'OH!")).when(mService).createUser(notNull(), anyInt(), 840 notNull()); 841 } 842 setExistingUsers(int... userIds)843 private void setExistingUsers(int... userIds) { 844 // TODO(b/197184481): move this logic to helper classes (UserTestingHelper.java & 845 // AndroidMockitoHelper.java) 846 List<UserHandle> userHandles = Arrays.stream(userIds) 847 .mapToObj(id -> UserHandle.of(id)) 848 .collect(Collectors.toList()); 849 when(mUserManager.getUserHandles(/* excludeDying= */ true)).thenReturn(userHandles); 850 } 851 mockIsHeadlessSystemUserMode(boolean mode)852 private void mockIsHeadlessSystemUserMode(boolean mode) { 853 mMgr = new CarUserManager(mCar, mService, mUserManager, 854 /* isHeadlessSystemUserMode= */ mode); 855 } 856 } 857