1 /* 2 * Copyright (C) 2019 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 17 package android.car.user; 18 19 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 20 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; 21 import static android.os.Process.myUid; 22 23 import static com.android.internal.util.FunctionalUtils.getLambdaName; 24 25 import android.annotation.CallbackExecutor; 26 import android.annotation.IntDef; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.RequiresPermission; 30 import android.annotation.SystemApi; 31 import android.annotation.TestApi; 32 import android.annotation.UserIdInt; 33 import android.car.Car; 34 import android.car.CarManagerBase; 35 import android.car.ICarUserService; 36 import android.car.util.concurrent.AndroidAsyncFuture; 37 import android.car.util.concurrent.AsyncFuture; 38 import android.content.pm.UserInfo; 39 import android.content.pm.UserInfo.UserInfoFlag; 40 import android.os.Bundle; 41 import android.os.IBinder; 42 import android.os.RemoteException; 43 import android.os.UserHandle; 44 import android.os.UserManager; 45 import android.provider.Settings; 46 import android.sysprop.CarProperties; 47 import android.util.ArrayMap; 48 import android.util.EventLog; 49 import android.util.Log; 50 51 import com.android.car.internal.common.CommonConstants; 52 import com.android.car.internal.common.CommonConstants.UserLifecycleEventType; 53 import com.android.car.internal.common.EventLogTags; 54 import com.android.car.internal.common.UserHelperLite; 55 import com.android.internal.annotations.GuardedBy; 56 import com.android.internal.annotations.VisibleForTesting; 57 import com.android.internal.infra.AndroidFuture; 58 import com.android.internal.os.IResultReceiver; 59 import com.android.internal.util.ArrayUtils; 60 import com.android.internal.util.Preconditions; 61 62 import java.lang.annotation.Retention; 63 import java.lang.annotation.RetentionPolicy; 64 import java.util.Arrays; 65 import java.util.List; 66 import java.util.Objects; 67 import java.util.concurrent.ExecutionException; 68 import java.util.concurrent.Executor; 69 import java.util.concurrent.TimeUnit; 70 import java.util.concurrent.TimeoutException; 71 import java.util.stream.Collectors; 72 73 /** 74 * API to manage users related to car. 75 * 76 * @hide 77 */ 78 @SystemApi 79 @TestApi 80 public final class CarUserManager extends CarManagerBase { 81 82 private static final String TAG = CarUserManager.class.getSimpleName(); 83 private static final int HAL_TIMEOUT_MS = CarProperties.user_hal_timeout().orElse(5_000); 84 private static final int REMOVE_USER_CALL_TIMEOUT_MS = 60_000; 85 86 private static final boolean DBG = false; 87 88 /** 89 * {@link UserLifecycleEvent} called when the user is starting, for components to initialize 90 * any per-user state they maintain for running users. 91 * 92 * @hide 93 */ 94 @SystemApi 95 @TestApi 96 public static final int USER_LIFECYCLE_EVENT_TYPE_STARTING = 97 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STARTING; 98 99 /** 100 * {@link UserLifecycleEvent} called when switching to a different foreground user, for 101 * components that have special behavior for whichever user is currently in the foreground. 102 * 103 * <p>This is called before any application processes are aware of the new user. 104 * 105 * <p>Notice that internal system services might not have handled user switching yet, so be 106 * careful with interaction with them. 107 * 108 * @hide 109 */ 110 @SystemApi 111 @TestApi 112 public static final int USER_LIFECYCLE_EVENT_TYPE_SWITCHING = 113 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_SWITCHING; 114 115 /** 116 * {@link UserLifecycleEvent} called when an existing user is in the process of being unlocked. 117 * 118 * <p>This means the credential-encrypted storage for that user is now available, and 119 * encryption-aware component filtering is no longer in effect. 120 * 121 * <p>Notice that internal system services might not have handled unlock yet, so most components 122 * should ignore this callback and rely on {@link #USER_LIFECYCLE_EVENT_TYPE_UNLOCKED} instead. 123 * 124 * @hide 125 */ 126 @SystemApi 127 @TestApi 128 public static final int USER_LIFECYCLE_EVENT_TYPE_UNLOCKING = 129 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING; 130 131 /** 132 * {@link UserLifecycleEvent} called after an existing user is unlocked. 133 * 134 * @hide 135 */ 136 @SystemApi 137 @TestApi 138 public static final int USER_LIFECYCLE_EVENT_TYPE_UNLOCKED = 139 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED; 140 141 /** 142 * {@link UserLifecycleEvent} called when an existing user is stopping, for components to 143 * finalize any per-user state they maintain for running users. 144 * 145 * <p>This is called prior to sending the {@code SHUTDOWN} broadcast to the user; it is a good 146 * place to stop making use of any resources of that user (such as binding to a service running 147 * in the user). 148 * 149 * <p><b>Note:</b> this is the last callback where the callee may access the target user's CE 150 * storage. 151 * 152 * @hide 153 */ 154 @SystemApi 155 @TestApi 156 public static final int USER_LIFECYCLE_EVENT_TYPE_STOPPING = 157 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STOPPING; 158 159 /** 160 * {@link UserLifecycleEvent} called after an existing user is stopped. 161 * 162 * <p>This is called after all application process teardown of the user is complete. 163 * 164 * @hide 165 */ 166 @SystemApi 167 @TestApi 168 public static final int USER_LIFECYCLE_EVENT_TYPE_STOPPED = 169 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STOPPED; 170 171 /** @hide */ 172 public static final String BUNDLE_PARAM_ACTION = "action"; 173 /** @hide */ 174 public static final String BUNDLE_PARAM_PREVIOUS_USER_ID = "previous_user"; 175 176 /** 177 * {@link UserIdentificationAssociationType} for key fob. 178 * 179 * @hide 180 */ 181 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_KEY_FOB = 1; 182 183 /** 184 * {@link UserIdentificationAssociationType} for custom type 1. 185 * 186 * @hide 187 */ 188 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_1 = 101; 189 190 /** 191 * {@link UserIdentificationAssociationType} for custom type 2. 192 * 193 * @hide 194 */ 195 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_2 = 102; 196 197 /** 198 * {@link UserIdentificationAssociationType} for custom type 3. 199 * 200 * @hide 201 */ 202 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_3 = 103; 203 204 /** 205 * {@link UserIdentificationAssociationType} for custom type 4. 206 * 207 * @hide 208 */ 209 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_4 = 104; 210 211 /** 212 * User HAL's user identification association types 213 * 214 * @hide 215 */ 216 @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_TYPE_" }, value = { 217 USER_IDENTIFICATION_ASSOCIATION_TYPE_KEY_FOB, 218 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_1, 219 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_2, 220 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_3, 221 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_4, 222 }) 223 @Retention(RetentionPolicy.SOURCE) 224 public @interface UserIdentificationAssociationType{} 225 226 /** 227 * {@link UserIdentificationAssociationSetValue} to associate the identification type with the 228 * current foreground Android user. 229 * 230 * @hide 231 */ 232 public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_ASSOCIATE_CURRENT_USER = 1; 233 234 /** 235 * {@link UserIdentificationAssociationSetValue} to disassociate the identification type from 236 * the current foreground Android user. 237 * 238 * @hide 239 */ 240 public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_CURRENT_USER = 2; 241 242 /** 243 * {@link UserIdentificationAssociationSetValue} to disassociate the identification type from 244 * all Android users. 245 * 246 * @hide 247 */ 248 public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_ALL_USERS = 3; 249 250 /** 251 * User HAL's user identification association types 252 * 253 * @hide 254 */ 255 @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_" }, value = { 256 USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_ASSOCIATE_CURRENT_USER, 257 USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_CURRENT_USER, 258 USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_ALL_USERS, 259 }) 260 @Retention(RetentionPolicy.SOURCE) 261 public @interface UserIdentificationAssociationSetValue{} 262 263 /** 264 * {@link UserIdentificationAssociationValue} when the status of an association could not be 265 * determined. 266 * 267 * @hide 268 */ 269 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_UNKNOWN = 1; 270 271 /** 272 * {@link UserIdentificationAssociationValue} when the identification type is associated with 273 * the current foreground Android user. 274 * 275 * @hide 276 */ 277 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATE_CURRENT_USER = 2; 278 279 /** 280 * {@link UserIdentificationAssociationValue} when the identification type is associated with 281 * another Android user. 282 * 283 * @hide 284 */ 285 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATED_ANOTHER_USER = 3; 286 287 /** 288 * {@link UserIdentificationAssociationValue} when the identification type is not associated 289 * with any Android user. 290 * 291 * @hide 292 */ 293 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_NOT_ASSOCIATED_ANY_USER = 4; 294 295 /** 296 * User HAL's user identification association types 297 * 298 * @hide 299 */ 300 @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_VALUE_" }, value = { 301 USER_IDENTIFICATION_ASSOCIATION_VALUE_UNKNOWN, 302 USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATE_CURRENT_USER, 303 USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATED_ANOTHER_USER, 304 USER_IDENTIFICATION_ASSOCIATION_VALUE_NOT_ASSOCIATED_ANY_USER, 305 }) 306 @Retention(RetentionPolicy.SOURCE) 307 public @interface UserIdentificationAssociationValue{} 308 309 private final Object mLock = new Object(); 310 311 private final ICarUserService mService; 312 private final UserManager mUserManager; 313 314 /** 315 * Map of listeners registers by the app. 316 */ 317 @Nullable 318 @GuardedBy("mLock") 319 private ArrayMap<UserLifecycleListener, Executor> mListeners; 320 321 /** 322 * Receiver used to receive user-lifecycle callbacks from the service. 323 */ 324 @Nullable 325 @GuardedBy("mLock") 326 private LifecycleResultReceiver mReceiver; 327 328 /** 329 * @hide 330 */ CarUserManager(@onNull Car car, @NonNull IBinder service)331 public CarUserManager(@NonNull Car car, @NonNull IBinder service) { 332 this(car, ICarUserService.Stub.asInterface(service), UserManager.get(car.getContext())); 333 } 334 335 /** 336 * @hide 337 */ 338 @VisibleForTesting CarUserManager(@onNull Car car, @NonNull ICarUserService service, @NonNull UserManager userManager)339 public CarUserManager(@NonNull Car car, @NonNull ICarUserService service, 340 @NonNull UserManager userManager) { 341 super(car); 342 343 mService = service; 344 mUserManager = userManager; 345 } 346 347 /** 348 * Switches the foreground user to the given target user. 349 * 350 * @hide 351 */ 352 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 353 android.Manifest.permission.CREATE_USERS}) switchUser(@serIdInt int targetUserId)354 public AsyncFuture<UserSwitchResult> switchUser(@UserIdInt int targetUserId) { 355 int uid = myUid(); 356 try { 357 AndroidFuture<UserSwitchResult> future = new AndroidFuture<UserSwitchResult>() { 358 @Override 359 protected void onCompleted(UserSwitchResult result, Throwable err) { 360 if (result != null) { 361 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SWITCH_USER_RESP, uid, 362 result.getStatus(), result.getErrorMessage()); 363 } else { 364 Log.w(TAG, "switchUser(" + targetUserId + ") failed: " + err); 365 } 366 super.onCompleted(result, err); 367 } 368 }; 369 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SWITCH_USER_REQ, uid, targetUserId); 370 mService.switchUser(targetUserId, HAL_TIMEOUT_MS, future); 371 return new AndroidAsyncFuture<>(future); 372 } catch (SecurityException e) { 373 throw e; 374 } catch (RemoteException | RuntimeException e) { 375 AsyncFuture<UserSwitchResult> future = 376 newSwitchResuiltForFailure(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 377 return handleExceptionFromCarService(e, future); 378 } 379 } 380 newSwitchResuiltForFailure( @serSwitchResult.Status int status)381 private AndroidAsyncFuture<UserSwitchResult> newSwitchResuiltForFailure( 382 @UserSwitchResult.Status int status) { 383 AndroidFuture<UserSwitchResult> future = new AndroidFuture<>(); 384 future.complete(new UserSwitchResult(status, null)); 385 return new AndroidAsyncFuture<>(future); 386 } 387 388 /** 389 * Creates a new Android user. 390 * 391 * @hide 392 */ 393 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 394 android.Manifest.permission.CREATE_USERS}) createUser(@ullable String name, @NonNull String userType, @UserInfoFlag int flags)395 public AsyncFuture<UserCreationResult> createUser(@Nullable String name, 396 @NonNull String userType, @UserInfoFlag int flags) { 397 int uid = myUid(); 398 try { 399 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>() { 400 @Override 401 protected void onCompleted(UserCreationResult result, Throwable err) { 402 if (result != null) { 403 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_CREATE_USER_RESP, uid, 404 result.getStatus(), result.getErrorMessage()); 405 UserInfo user = result.getUser(); 406 if (result.isSuccess() && user != null && user.isGuest()) { 407 onGuestCreated(user); 408 } 409 } else { 410 Log.w(TAG, "createUser(" + userType + "," + UserInfo.flagsToString(flags) 411 + ") failed: " + err); 412 } 413 super.onCompleted(result, err); 414 }; 415 }; 416 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_CREATE_USER_REQ, uid, 417 UserHelperLite.safeName(name), userType, flags); 418 mService.createUser(name, userType, flags, HAL_TIMEOUT_MS, future); 419 return new AndroidAsyncFuture<>(future); 420 } catch (SecurityException e) { 421 throw e; 422 } catch (RemoteException | RuntimeException e) { 423 AndroidFuture<UserCreationResult> future = new AndroidFuture<>(); 424 future.complete(new UserCreationResult(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE)); 425 return handleExceptionFromCarService(e, new AndroidAsyncFuture<>(future)); 426 } 427 } 428 429 /** 430 * Creates a new guest Android user. 431 * 432 * @hide 433 */ 434 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 435 android.Manifest.permission.CREATE_USERS}) createGuest(@ullable String name)436 public AsyncFuture<UserCreationResult> createGuest(@Nullable String name) { 437 return createUser(name, UserManager.USER_TYPE_FULL_GUEST, /* flags= */ 0); 438 } 439 440 /** 441 * Creates a new Android user. 442 * 443 * @hide 444 */ 445 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 446 android.Manifest.permission.CREATE_USERS}) createUser(@ullable String name, @UserInfoFlag int flags)447 public AsyncFuture<UserCreationResult> createUser(@Nullable String name, 448 @UserInfoFlag int flags) { 449 return createUser(name, UserManager.USER_TYPE_FULL_SECONDARY, flags); 450 } 451 452 /** 453 * Updates pre-created users. 454 * <p> 455 * Updates pre-created users based on the car properties defined 456 * {@code CarProperties.number_pre_created_guests} and (@code 457 * CarProperties.number_pre_created_users}. 458 * 459 * @hide 460 */ 461 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 462 android.Manifest.permission.CREATE_USERS}) updatePreCreatedUsers()463 public void updatePreCreatedUsers() { 464 int uid = myUid(); 465 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_PRE_CREATE_USER_REQ, uid); 466 try { 467 mService.updatePreCreatedUsers(); 468 } catch (SecurityException e) { 469 throw e; 470 } catch (RemoteException | RuntimeException e) { 471 handleExceptionFromCarService(e, null); 472 } 473 } 474 475 // TODO(b/159283854): move to UserManager onGuestCreated(UserInfo user)476 private void onGuestCreated(UserInfo user) { 477 Settings.Secure.putStringForUser(getContext().getContentResolver(), 478 Settings.Secure.SKIP_FIRST_USE_HINTS, "1", user.id); 479 } 480 481 /** 482 * Removes the given user. 483 * 484 * @param userId identification of the user to be removed. 485 * 486 * @return whether the user was successfully removed. 487 * 488 * @hide 489 */ 490 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 491 android.Manifest.permission.CREATE_USERS}) 492 @NonNull removeUser(@serIdInt int userId)493 public UserRemovalResult removeUser(@UserIdInt int userId) { 494 int uid = myUid(); 495 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_REMOVE_USER_REQ, uid, userId); 496 int status = UserRemovalResult.STATUS_ANDROID_FAILURE; 497 try { 498 AndroidFuture<UserRemovalResult> future = new AndroidFuture<UserRemovalResult>(); 499 mService.removeUser(userId, future); 500 UserRemovalResult result = future.get(REMOVE_USER_CALL_TIMEOUT_MS, 501 TimeUnit.MILLISECONDS); 502 status = result.getStatus(); 503 return result; 504 } catch (SecurityException e) { 505 throw e; 506 } catch (InterruptedException e) { 507 Thread.currentThread().interrupt(); 508 return new UserRemovalResult(UserRemovalResult.STATUS_ANDROID_FAILURE); 509 } catch (ExecutionException | TimeoutException e) { 510 return new UserRemovalResult(UserRemovalResult.STATUS_ANDROID_FAILURE); 511 } catch (RemoteException | RuntimeException e) { 512 return handleExceptionFromCarService(e, 513 new UserRemovalResult(UserRemovalResult.STATUS_ANDROID_FAILURE)); 514 } finally { 515 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_REMOVE_USER_RESP, uid, status); 516 } 517 } 518 519 /** 520 * Adds a listener for {@link UserLifecycleEvent user lifecycle events}. 521 * 522 * @throws IllegalStateException if the listener was already added. 523 * 524 * @hide 525 */ 526 @SystemApi 527 @TestApi 528 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleListener listener)529 public void addListener(@NonNull @CallbackExecutor Executor executor, 530 @NonNull UserLifecycleListener listener) { 531 Objects.requireNonNull(executor, "executor cannot be null"); 532 Objects.requireNonNull(listener, "listener cannot be null"); 533 534 int uid = myUid(); 535 String packageName = getContext().getPackageName(); 536 if (DBG) { 537 Log.d(TAG, "addListener(): uid=" + uid + ", pkg=" + packageName 538 + ", listener=" + listener); 539 } 540 synchronized (mLock) { 541 Preconditions.checkState(mListeners == null || !mListeners.containsKey(listener), 542 "already called for this listener"); 543 if (mReceiver == null) { 544 mReceiver = new LifecycleResultReceiver(); 545 try { 546 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_ADD_LISTENER, uid, packageName); 547 if (DBG) { 548 Log.d(TAG, "Setting lifecycle receiver for uid " + uid + " and package " 549 + packageName); 550 } 551 mService.setLifecycleListenerForApp(packageName, mReceiver); 552 } catch (RemoteException e) { 553 handleRemoteExceptionFromCarService(e); 554 } 555 } else { 556 if (DBG) { 557 Log.d(TAG, "Already set receiver for uid " + uid + " and package " 558 + packageName); 559 } 560 } 561 562 if (mListeners == null) { 563 mListeners = new ArrayMap<>(1); // Most likely app will have just one listener 564 } else if (DBG) { 565 Log.d(TAG, "addListener(" + getLambdaName(listener) + "): context " + getContext() 566 + " already has " + mListeners.size() + " listeners: " 567 + mListeners.keySet().stream() 568 .map((l) -> getLambdaName(l)) 569 .collect(Collectors.toList()), new Exception("caller's stack")); 570 } 571 if (DBG) Log.d(TAG, "Adding listener: " + listener); 572 mListeners.put(listener, executor); 573 } 574 } 575 576 /** 577 * Removes a listener for {@link UserLifecycleEvent user lifecycle events}. 578 * 579 * @throws IllegalStateException if the listener was not added beforehand. 580 * 581 * @hide 582 */ 583 @SystemApi 584 @TestApi 585 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) removeListener(@onNull UserLifecycleListener listener)586 public void removeListener(@NonNull UserLifecycleListener listener) { 587 Objects.requireNonNull(listener, "listener cannot be null"); 588 589 int uid = myUid(); 590 String packageName = getContext().getPackageName(); 591 if (DBG) { 592 Log.d(TAG, "removeListener(): uid=" + uid + ", pkg=" + packageName 593 + ", listener=" + listener); 594 } 595 synchronized (mLock) { 596 Preconditions.checkState(mListeners != null && mListeners.containsKey(listener), 597 "not called for this listener yet"); 598 mListeners.remove(listener); 599 600 if (!mListeners.isEmpty()) { 601 if (DBG) Log.d(TAG, "removeListeners(): still " + mListeners.size() + " left"); 602 return; 603 } 604 mListeners = null; 605 606 if (mReceiver == null) { 607 Log.wtf(TAG, "removeListener(): receiver already null"); 608 return; 609 } 610 611 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_REMOVE_LISTENER, uid, packageName); 612 if (DBG) { 613 Log.d(TAG, "Removing lifecycle receiver for uid=" + uid + " and package " 614 + packageName); 615 } 616 try { 617 mService.resetLifecycleListenerForApp(mReceiver); 618 mReceiver = null; 619 } catch (RemoteException e) { 620 handleRemoteExceptionFromCarService(e); 621 } 622 } 623 } 624 625 /** 626 * Check if user hal supports user association. 627 * 628 * @hide 629 */ isUserHalUserAssociationSupported()630 public boolean isUserHalUserAssociationSupported() { 631 try { 632 return mService.isUserHalUserAssociationSupported(); 633 } catch (RemoteException | RuntimeException e) { 634 return handleExceptionFromCarService(e, false); 635 } 636 } 637 638 /** 639 * Gets the user authentication types associated with this manager's user. 640 * 641 * @hide 642 */ 643 @NonNull 644 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 645 android.Manifest.permission.CREATE_USERS}) getUserIdentificationAssociation( @serIdentificationAssociationType int... types)646 public UserIdentificationAssociationResponse getUserIdentificationAssociation( 647 @UserIdentificationAssociationType int... types) { 648 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 649 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_REQ, types.length); 650 try { 651 UserIdentificationAssociationResponse response = 652 mService.getUserIdentificationAssociation(types); 653 if (response != null) { 654 int[] values = response.getValues(); 655 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_GET_USER_AUTH_RESP, 656 values != null ? values.length : 0); 657 } 658 return response; 659 } catch (SecurityException e) { 660 throw e; 661 } catch (RemoteException | RuntimeException e) { 662 return handleExceptionFromCarService(e, 663 UserIdentificationAssociationResponse.forFailure(e.getMessage())); 664 } 665 } 666 667 /** 668 * Sets the user authentication types associated with this manager's user. 669 * 670 * @hide 671 */ 672 @NonNull 673 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 674 android.Manifest.permission.CREATE_USERS}) setUserIdentificationAssociation( @serIdentificationAssociationType int[] types, @UserIdentificationAssociationSetValue int[] values)675 public AsyncFuture<UserIdentificationAssociationResponse> setUserIdentificationAssociation( 676 @UserIdentificationAssociationType int[] types, 677 @UserIdentificationAssociationSetValue int[] values) { 678 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 679 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value"); 680 if (types.length != values.length) { 681 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values (" 682 + Arrays.toString(values) + ") should have the same length"); 683 } 684 // TODO(b/153900032): move this logic to a common helper 685 Object[] loggedValues = new Integer[types.length * 2]; 686 for (int i = 0; i < types.length; i++) { 687 loggedValues[i * 2] = types[i]; 688 loggedValues[i * 2 + 1 ] = values[i]; 689 } 690 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_REQ, loggedValues); 691 692 try { 693 AndroidFuture<UserIdentificationAssociationResponse> future = 694 new AndroidFuture<UserIdentificationAssociationResponse>() { 695 @Override 696 protected void onCompleted(UserIdentificationAssociationResponse result, 697 Throwable err) { 698 if (result != null) { 699 int[] rawValues = result.getValues(); 700 // TODO(b/153900032): move this logic to a common helper 701 if (rawValues != null) { 702 Object[] loggedValues = new Object[rawValues.length]; 703 for (int i = 0; i < rawValues.length; i++) { 704 loggedValues[i] = rawValues[i]; 705 } 706 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_SET_USER_AUTH_RESP, 707 loggedValues); 708 } 709 } else { 710 Log.w(TAG, "setUserIdentificationAssociation(" + Arrays.toString(types) 711 + ", " + Arrays.toString(values) + ") failed: " + err); 712 } 713 super.onCompleted(result, err); 714 }; 715 }; 716 mService.setUserIdentificationAssociation(HAL_TIMEOUT_MS, types, values, future); 717 return new AndroidAsyncFuture<>(future); 718 } catch (SecurityException e) { 719 throw e; 720 } catch (RemoteException | RuntimeException e) { 721 AndroidFuture<UserIdentificationAssociationResponse> future = new AndroidFuture<>(); 722 future.complete(UserIdentificationAssociationResponse.forFailure()); 723 return handleExceptionFromCarService(e, new AndroidAsyncFuture<>(future)); 724 } 725 } 726 727 /** 728 * Sets a callback to be notified before user switch. It should only be used by Car System UI. 729 * 730 * @hide 731 */ 732 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) setUserSwitchUiCallback(@onNull UserSwitchUiCallback callback)733 public void setUserSwitchUiCallback(@NonNull UserSwitchUiCallback callback) { 734 Preconditions.checkArgument(callback != null, "Null callback"); 735 UserSwitchUiCallbackReceiver userSwitchUiCallbackReceiver = 736 new UserSwitchUiCallbackReceiver(callback); 737 try { 738 mService.setUserSwitchUiCallback(userSwitchUiCallbackReceiver); 739 } catch (RemoteException e) { 740 handleRemoteExceptionFromCarService(e); 741 } 742 } 743 744 /** 745 * {@code IResultReceiver} used to receive user switch UI Callback. 746 */ 747 // TODO(b/154958003): use mReceiver instead as now there are two binder objects 748 private final class UserSwitchUiCallbackReceiver extends IResultReceiver.Stub { 749 750 private final UserSwitchUiCallback mUserSwitchUiCallback; 751 UserSwitchUiCallbackReceiver(UserSwitchUiCallback callback)752 UserSwitchUiCallbackReceiver(UserSwitchUiCallback callback) { 753 mUserSwitchUiCallback = callback; 754 } 755 756 @Override send(int userId, Bundle unused)757 public void send(int userId, Bundle unused) throws RemoteException { 758 mUserSwitchUiCallback.showUserSwitchDialog(userId); 759 } 760 } 761 762 /** 763 * {@code IResultReceiver} used to receive lifecycle events and dispatch to the proper listener. 764 */ 765 private class LifecycleResultReceiver extends IResultReceiver.Stub { 766 @Override send(int resultCode, Bundle resultData)767 public void send(int resultCode, Bundle resultData) { 768 if (resultData == null) { 769 Log.w(TAG, "Received result (" + resultCode + ") without data"); 770 return; 771 } 772 int from = resultData.getInt(BUNDLE_PARAM_PREVIOUS_USER_ID, UserHandle.USER_NULL); 773 int to = resultCode; 774 int eventType = resultData.getInt(BUNDLE_PARAM_ACTION); 775 UserLifecycleEvent event = new UserLifecycleEvent(eventType, from, to); 776 ArrayMap<UserLifecycleListener, Executor> listeners; 777 synchronized (mLock) { 778 if (mListeners == null) { 779 Log.w(TAG, "No listeners for event " + event); 780 return; 781 } 782 listeners = new ArrayMap<>(mListeners); 783 } 784 int size = listeners.size(); 785 EventLog.writeEvent(EventLogTags.CAR_USER_MGR_NOTIFY_LIFECYCLE_LISTENER, 786 size, eventType, from, to); 787 for (int i = 0; i < size; i++) { 788 UserLifecycleListener listener = listeners.keyAt(i); 789 Executor executor = listeners.valueAt(i); 790 if (DBG) { 791 Log.d(TAG, "Calling " + getLambdaName(listener) + " for event " + event); 792 } 793 executor.execute(() -> listener.onEvent(event)); 794 } 795 } 796 } 797 798 /** @hide */ 799 @Override onCarDisconnected()800 public void onCarDisconnected() { 801 // nothing to do 802 } 803 804 /** 805 * @hide 806 */ 807 @TestApi lifecycleEventTypeToString(@serLifecycleEventType int type)808 public static String lifecycleEventTypeToString(@UserLifecycleEventType int type) { 809 switch (type) { 810 case USER_LIFECYCLE_EVENT_TYPE_STARTING: 811 return "STARTING"; 812 case USER_LIFECYCLE_EVENT_TYPE_SWITCHING: 813 return "SWITCHING"; 814 case USER_LIFECYCLE_EVENT_TYPE_UNLOCKING: 815 return "UNLOCKING"; 816 case USER_LIFECYCLE_EVENT_TYPE_UNLOCKED: 817 return "UNLOCKED"; 818 case USER_LIFECYCLE_EVENT_TYPE_STOPPING: 819 return "STOPPING"; 820 case USER_LIFECYCLE_EVENT_TYPE_STOPPED: 821 return "STOPPED"; 822 default: 823 return "UNKNOWN-" + type; 824 } 825 } 826 827 // NOTE: this method is called by ExperimentalCarUserManager, so it can get the mService. 828 // "Real" ExperimentalCarUserManager instances should be obtained through 829 // ExperimentalCarUserManager.from(mCarUserManager) 830 // instead. newExperimentalCarUserManager()831 ExperimentalCarUserManager newExperimentalCarUserManager() { 832 return new ExperimentalCarUserManager(mCar, mService); 833 } 834 835 /** 836 * Checks if the given {@code userId} represents a valid user. 837 * 838 * <p>A "valid" user: 839 * 840 * <ul> 841 * <li>Must exist in the device. 842 * <li>Is not in the process of being deleted. 843 * <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use 844 * {@link UserManager#isHeadlessSystemUserMode() headless system mode}. 845 * </ul> 846 * 847 * @hide 848 */ 849 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 850 android.Manifest.permission.CREATE_USERS}) isValidUser(@serIdInt int userId)851 public boolean isValidUser(@UserIdInt int userId) { 852 List<UserInfo> allUsers = mUserManager.getAliveUsers(); 853 for (int i = 0; i < allUsers.size(); i++) { 854 UserInfo user = allUsers.get(i); 855 if (user.id == userId && (userId != UserHandle.USER_SYSTEM 856 || !UserManager.isHeadlessSystemUserMode())) { 857 return true; 858 } 859 } 860 return false; 861 } 862 863 /** 864 * Defines a lifecycle event for an Android user. 865 * 866 * @hide 867 */ 868 @SystemApi 869 @TestApi 870 public static final class UserLifecycleEvent { 871 private final @UserLifecycleEventType int mEventType; 872 private final @UserIdInt int mUserId; 873 private final @UserIdInt int mPreviousUserId; 874 875 /** @hide */ UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int from, @UserIdInt int to)876 public UserLifecycleEvent(@UserLifecycleEventType int eventType, 877 @UserIdInt int from, @UserIdInt int to) { 878 mEventType = eventType; 879 mPreviousUserId = from; 880 mUserId = to; 881 } 882 883 /** @hide */ UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int to)884 public UserLifecycleEvent(@UserLifecycleEventType int eventType, @UserIdInt int to) { 885 this(eventType, UserHandle.USER_NULL, to); 886 } 887 888 /** 889 * Gets the event type. 890 * 891 * @return either {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STARTING}, 892 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}, 893 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKING}, 894 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKED}, 895 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPING}, or 896 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPED}. 897 */ 898 @UserLifecycleEventType getEventType()899 public int getEventType() { 900 return mEventType; 901 } 902 903 /** 904 * Gets the id of the user whose event is being reported. 905 * 906 * @hide 907 */ 908 @UserIdInt getUserId()909 public int getUserId() { 910 return mUserId; 911 } 912 913 /** 914 * Gets the handle of the user whose event is being reported. 915 */ 916 @NonNull getUserHandle()917 public UserHandle getUserHandle() { 918 return UserHandle.of(mUserId); 919 } 920 921 /** 922 * Gets the id of the user being switched from. 923 * 924 * <p>This method returns {@link UserHandle#USER_NULL} for all event types but 925 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}. 926 * 927 * @hide 928 */ 929 @UserIdInt getPreviousUserId()930 public int getPreviousUserId() { 931 return mPreviousUserId; 932 } 933 934 /** 935 * Gets the handle of the user being switched from. 936 * 937 * <p>This method returns {@code null} for all event types but 938 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}. 939 */ 940 @Nullable getPreviousUserHandle()941 public UserHandle getPreviousUserHandle() { 942 return mPreviousUserId == UserHandle.USER_NULL ? null : UserHandle.of(mPreviousUserId); 943 } 944 945 @Override toString()946 public String toString() { 947 StringBuilder builder = new StringBuilder("Event[type=") 948 .append(lifecycleEventTypeToString(mEventType)); 949 if (mPreviousUserId != UserHandle.USER_NULL) { 950 builder 951 .append(",from=").append(mPreviousUserId) 952 .append(",to=").append(mUserId); 953 } else { 954 builder.append(",user=").append(mUserId); 955 } 956 957 return builder.append(']').toString(); 958 } 959 } 960 961 /** 962 * Listener for Android User lifecycle events. 963 * 964 * <p>Must be registered using {@link CarUserManager#addListener(UserLifecycleListener)} and 965 * unregistered through {@link CarUserManager#removeListener(UserLifecycleListener)}. 966 * 967 * @hide 968 */ 969 @SystemApi 970 @TestApi 971 public interface UserLifecycleListener { 972 973 /** 974 * Called to notify the given {@code event}. 975 */ onEvent(@onNull UserLifecycleEvent event)976 void onEvent(@NonNull UserLifecycleEvent event); 977 } 978 979 /** 980 * Callback for notifying user switch before switch started. 981 * 982 * <p> It should only be user by Car System UI. The purpose of this callback is notify the 983 * Car System UI to display the user switch UI. 984 * 985 * @hide 986 */ 987 public interface UserSwitchUiCallback { 988 989 /** 990 * Called to notify that user switch dialog should be shown now. 991 */ showUserSwitchDialog(@serIdInt int userId)992 void showUserSwitchDialog(@UserIdInt int userId); 993 } 994 } 995