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.car.internal.util.FunctionalUtils.getLambdaName; 24 import static com.android.car.internal.util.VersionUtils.assertPlatformVersionAtLeastU; 25 import static com.android.car.internal.util.VersionUtils.isPlatformVersionAtLeastU; 26 27 import android.annotation.CallbackExecutor; 28 import android.annotation.IntDef; 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.RequiresPermission; 32 import android.annotation.SystemApi; 33 import android.annotation.TestApi; 34 import android.annotation.UserIdInt; 35 import android.car.Car; 36 import android.car.CarManagerBase; 37 import android.car.ICarResultReceiver; 38 import android.car.ICarUserService; 39 import android.car.ResultCallback; 40 import android.car.SyncResultCallback; 41 import android.car.annotation.AddedInOrBefore; 42 import android.car.annotation.ApiRequirements; 43 import android.car.builtin.os.UserManagerHelper; 44 import android.car.builtin.util.EventLogHelper; 45 import android.car.util.concurrent.AndroidAsyncFuture; 46 import android.car.util.concurrent.AndroidFuture; 47 import android.car.util.concurrent.AsyncFuture; 48 import android.os.Bundle; 49 import android.os.IBinder; 50 import android.os.RemoteException; 51 import android.os.UserHandle; 52 import android.os.UserManager; 53 import android.util.ArrayMap; 54 import android.util.Dumpable; 55 import android.util.Log; 56 import android.util.Pair; 57 58 import com.android.car.internal.ResultCallbackImpl; 59 import com.android.car.internal.common.CommonConstants; 60 import com.android.car.internal.common.CommonConstants.UserLifecycleEventType; 61 import com.android.car.internal.common.UserHelperLite; 62 import com.android.car.internal.os.CarSystemProperties; 63 import com.android.car.internal.util.ArrayUtils; 64 import com.android.internal.annotations.GuardedBy; 65 import com.android.internal.annotations.VisibleForTesting; 66 import com.android.internal.util.Preconditions; 67 68 import java.io.PrintWriter; 69 import java.lang.annotation.Retention; 70 import java.lang.annotation.RetentionPolicy; 71 import java.util.ArrayList; 72 import java.util.Arrays; 73 import java.util.List; 74 import java.util.Objects; 75 import java.util.concurrent.Executor; 76 import java.util.concurrent.TimeUnit; 77 import java.util.concurrent.TimeoutException; 78 import java.util.stream.Collectors; 79 80 /** 81 * API to manage users related to car. 82 * 83 * @hide 84 */ 85 @SystemApi 86 public final class CarUserManager extends CarManagerBase { 87 88 /** @hide */ 89 @AddedInOrBefore(majorVersion = 33) 90 public static final String TAG = CarUserManager.class.getSimpleName(); 91 92 private static final int HAL_TIMEOUT_MS = CarSystemProperties.getUserHalTimeout().orElse(5_000); 93 private static final int USER_CALL_TIMEOUT_MS = 60_000; 94 95 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 96 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 97 98 /** 99 * {@link UserLifecycleEvent} called when the user is starting, for components to initialize 100 * any per-user state they maintain for running users. 101 * 102 * @hide 103 */ 104 @SystemApi 105 @AddedInOrBefore(majorVersion = 33) 106 public static final int USER_LIFECYCLE_EVENT_TYPE_STARTING = 107 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STARTING; 108 109 /** 110 * {@link UserLifecycleEvent} called when switching to a different foreground user, for 111 * components that have special behavior for whichever user is currently in the foreground. 112 * 113 * <p>This is called before any application processes are aware of the new user. 114 * 115 * <p>Notice that internal system services might not have handled user switching yet, so be 116 * careful with interaction with them. 117 * 118 * @hide 119 */ 120 @SystemApi 121 @AddedInOrBefore(majorVersion = 33) 122 public static final int USER_LIFECYCLE_EVENT_TYPE_SWITCHING = 123 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_SWITCHING; 124 125 /** 126 * {@link UserLifecycleEvent} called when an existing user is in the process of being unlocked. 127 * 128 * <p>This means the credential-encrypted storage for that user is now available, and 129 * encryption-aware component filtering is no longer in effect. 130 * 131 * <p>Notice that internal system services might not have handled unlock yet, so most components 132 * should ignore this callback and rely on {@link #USER_LIFECYCLE_EVENT_TYPE_UNLOCKED} instead. 133 * 134 * @hide 135 */ 136 @SystemApi 137 @AddedInOrBefore(majorVersion = 33) 138 public static final int USER_LIFECYCLE_EVENT_TYPE_UNLOCKING = 139 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING; 140 141 /** 142 * {@link UserLifecycleEvent} called after an existing user is unlocked. 143 * 144 * @hide 145 */ 146 @SystemApi 147 @AddedInOrBefore(majorVersion = 33) 148 public static final int USER_LIFECYCLE_EVENT_TYPE_UNLOCKED = 149 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED; 150 151 /** 152 * {@link UserLifecycleEvent} called after an existing user is unlocked for components to 153 * perform non-urgent tasks for user unlocked. 154 * 155 * <p>Note: This event type is intended only for internal system services. Application listeners 156 * should not use this event type and will not receive any events of this type. 157 * 158 * @hide 159 */ 160 @AddedInOrBefore(majorVersion = 33) 161 public static final int USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED = 162 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED; 163 164 /** 165 * {@link UserLifecycleEvent} called when an existing user is stopping, for components to 166 * finalize any per-user state they maintain for running users. 167 * 168 * <p>This is called prior to sending the {@code SHUTDOWN} broadcast to the user; it is a good 169 * place to stop making use of any resources of that user (such as binding to a service running 170 * in the user). 171 * 172 * <p><b>Note:</b> this is the last callback where the callee may access the target user's CE 173 * storage. 174 * 175 * @hide 176 */ 177 @SystemApi 178 @AddedInOrBefore(majorVersion = 33) 179 public static final int USER_LIFECYCLE_EVENT_TYPE_STOPPING = 180 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STOPPING; 181 182 /** 183 * {@link UserLifecycleEvent} called after an existing user is stopped. 184 * 185 * <p>This is called after all application process teardown of the user is complete. 186 * 187 * @hide 188 */ 189 @SystemApi 190 @AddedInOrBefore(majorVersion = 33) 191 public static final int USER_LIFECYCLE_EVENT_TYPE_STOPPED = 192 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STOPPED; 193 194 /** 195 * {@link UserLifecycleEvent} called after an existing user is created. 196 * 197 * @hide 198 */ 199 @SystemApi 200 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_1, 201 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_1) 202 public static final int USER_LIFECYCLE_EVENT_TYPE_CREATED = 203 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_CREATED; 204 205 /** 206 * {@link UserLifecycleEvent} called after an existing user is removed. 207 * 208 * @hide 209 */ 210 @SystemApi 211 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_1, 212 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_1) 213 public static final int USER_LIFECYCLE_EVENT_TYPE_REMOVED = 214 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_REMOVED; 215 216 /** 217 * {@link UserLifecycleEvent} called after an existing user becomes visible. 218 * 219 * @hide 220 */ 221 @SystemApi 222 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 223 minPlatformVersion = ApiRequirements.PlatformVersion.UPSIDE_DOWN_CAKE_0) 224 public static final int USER_LIFECYCLE_EVENT_TYPE_VISIBLE = 225 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_VISIBLE; 226 227 /** 228 * {@link UserLifecycleEvent} called after an existing user becomes invisible. 229 * 230 * @hide 231 */ 232 @SystemApi 233 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 234 minPlatformVersion = ApiRequirements.PlatformVersion.UPSIDE_DOWN_CAKE_0) 235 public static final int USER_LIFECYCLE_EVENT_TYPE_INVISIBLE = 236 CommonConstants.USER_LIFECYCLE_EVENT_TYPE_INVISIBLE; 237 238 /** @hide */ 239 @AddedInOrBefore(majorVersion = 33) 240 public static final String BUNDLE_PARAM_ACTION = "action"; 241 /** @hide */ 242 @AddedInOrBefore(majorVersion = 33) 243 public static final String BUNDLE_PARAM_PREVIOUS_USER_ID = "previous_user"; 244 245 /** 246 * {@link UserIdentificationAssociationType} for key fob. 247 * 248 * @hide 249 */ 250 @AddedInOrBefore(majorVersion = 33) 251 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_KEY_FOB = 1; 252 253 /** 254 * {@link UserIdentificationAssociationType} for custom type 1. 255 * 256 * @hide 257 */ 258 @AddedInOrBefore(majorVersion = 33) 259 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_1 = 101; 260 261 /** 262 * {@link UserIdentificationAssociationType} for custom type 2. 263 * 264 * @hide 265 */ 266 @AddedInOrBefore(majorVersion = 33) 267 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_2 = 102; 268 269 /** 270 * {@link UserIdentificationAssociationType} for custom type 3. 271 * 272 * @hide 273 */ 274 @AddedInOrBefore(majorVersion = 33) 275 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_3 = 103; 276 277 /** 278 * {@link UserIdentificationAssociationType} for custom type 4. 279 * 280 * @hide 281 */ 282 @AddedInOrBefore(majorVersion = 33) 283 public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_4 = 104; 284 285 /** 286 * User HAL's user identification association types 287 * 288 * @hide 289 */ 290 @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_TYPE_" }, value = { 291 USER_IDENTIFICATION_ASSOCIATION_TYPE_KEY_FOB, 292 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_1, 293 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_2, 294 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_3, 295 USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_4, 296 }) 297 @Retention(RetentionPolicy.SOURCE) 298 public @interface UserIdentificationAssociationType{} 299 300 /** 301 * {@link UserIdentificationAssociationSetValue} to associate the identification type with the 302 * current foreground Android user. 303 * 304 * @hide 305 */ 306 @AddedInOrBefore(majorVersion = 33) 307 public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_ASSOCIATE_CURRENT_USER = 1; 308 309 /** 310 * {@link UserIdentificationAssociationSetValue} to disassociate the identification type from 311 * the current foreground Android user. 312 * 313 * @hide 314 */ 315 @AddedInOrBefore(majorVersion = 33) 316 public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_CURRENT_USER = 2; 317 318 /** 319 * {@link UserIdentificationAssociationSetValue} to disassociate the identification type from 320 * all Android users. 321 * 322 * @hide 323 */ 324 @AddedInOrBefore(majorVersion = 33) 325 public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_ALL_USERS = 3; 326 327 /** 328 * User HAL's user identification association types 329 * 330 * @hide 331 */ 332 @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_" }, value = { 333 USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_ASSOCIATE_CURRENT_USER, 334 USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_CURRENT_USER, 335 USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_ALL_USERS, 336 }) 337 @Retention(RetentionPolicy.SOURCE) 338 public @interface UserIdentificationAssociationSetValue{} 339 340 /** 341 * {@link UserIdentificationAssociationValue} when the status of an association could not be 342 * determined. 343 * 344 * @hide 345 */ 346 @AddedInOrBefore(majorVersion = 33) 347 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_UNKNOWN = 1; 348 349 /** 350 * {@link UserIdentificationAssociationValue} when the identification type is associated with 351 * the current foreground Android user. 352 * 353 * @hide 354 */ 355 @AddedInOrBefore(majorVersion = 33) 356 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATE_CURRENT_USER = 2; 357 358 /** 359 * {@link UserIdentificationAssociationValue} when the identification type is associated with 360 * another Android user. 361 * 362 * @hide 363 */ 364 @AddedInOrBefore(majorVersion = 33) 365 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATED_ANOTHER_USER = 3; 366 367 /** 368 * {@link UserIdentificationAssociationValue} when the identification type is not associated 369 * with any Android user. 370 * 371 * @hide 372 */ 373 @AddedInOrBefore(majorVersion = 33) 374 public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_NOT_ASSOCIATED_ANY_USER = 4; 375 376 /** 377 * User HAL's user identification association types 378 * 379 * @hide 380 */ 381 @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_VALUE_" }, value = { 382 USER_IDENTIFICATION_ASSOCIATION_VALUE_UNKNOWN, 383 USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATE_CURRENT_USER, 384 USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATED_ANOTHER_USER, 385 USER_IDENTIFICATION_ASSOCIATION_VALUE_NOT_ASSOCIATED_ANY_USER, 386 }) 387 @Retention(RetentionPolicy.SOURCE) 388 public @interface UserIdentificationAssociationValue{} 389 390 private final Object mLock = new Object(); 391 392 private final ICarUserService mService; 393 private final UserManager mUserManager; 394 395 /** 396 * Map of listeners registers by the app. 397 */ 398 @Nullable 399 @GuardedBy("mLock") 400 private ArrayMap<UserLifecycleListener, Pair<UserLifecycleEventFilter, Executor>> mListeners; 401 402 /** 403 * Receiver used to receive user-lifecycle callbacks from the service. 404 */ 405 @Nullable 406 @GuardedBy("mLock") 407 private LifecycleResultReceiver mReceiver; 408 409 private final Dumper mDumper; 410 411 /** 412 * Logs the number of received events so it's shown on {@code Dumper.dump()}. 413 */ 414 private int mNumberReceivedEvents; 415 416 /** 417 * Logs the received events so they're shown on {@code Dumper.dump()}. 418 * 419 * <p><b>Note</b>: these events are only logged when {@link #VERBOSE} is {@code true}. 420 */ 421 @Nullable 422 private List<UserLifecycleEvent> mEvents; 423 424 /** 425 * @hide 426 */ CarUserManager(@onNull Car car, @NonNull IBinder service)427 public CarUserManager(@NonNull Car car, @NonNull IBinder service) { 428 this(car, ICarUserService.Stub.asInterface(service), 429 car.getContext().getSystemService(UserManager.class)); 430 } 431 432 /** 433 * @hide 434 */ 435 @VisibleForTesting CarUserManager(@onNull Car car, @NonNull ICarUserService service, @NonNull UserManager userManager)436 public CarUserManager(@NonNull Car car, @NonNull ICarUserService service, 437 @NonNull UserManager userManager) { 438 super(car); 439 440 mDumper = addDumpable(car.getContext(), () -> new Dumper()); 441 Log.d(TAG, "CarUserManager(): DBG= " + DBG + ", mDumper=" + mDumper); 442 443 mService = service; 444 mUserManager = userManager; 445 } 446 447 /** 448 * Starts the specified user. 449 * 450 * @hide 451 */ 452 @SystemApi 453 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 454 android.Manifest.permission.INTERACT_ACROSS_USERS}) 455 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 456 minPlatformVersion = ApiRequirements.PlatformVersion.UPSIDE_DOWN_CAKE_0) startUser(@onNull UserStartRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserStartResponse> callback)457 public void startUser(@NonNull UserStartRequest request, 458 @NonNull @CallbackExecutor Executor executor, 459 @NonNull ResultCallback<UserStartResponse> callback) { 460 assertPlatformVersionAtLeastU(); 461 int uid = myUid(); 462 int userId = request.getUserHandle().getIdentifier(); 463 int displayId = request.getDisplayId(); 464 if (isPlatformVersionAtLeastU()) { 465 EventLogHelper.writeCarUserManagerStartUserReq(uid, userId, displayId); 466 } 467 try { 468 ResultCallbackImpl<UserStartResponse> callbackImpl = new ResultCallbackImpl<>( 469 executor, callback) { 470 @Override 471 protected void onCompleted(UserStartResponse response) { 472 if (isPlatformVersionAtLeastU()) { 473 EventLogHelper.writeCarUserManagerStartUserResp(uid, userId, displayId, 474 response != null ? response.getStatus() 475 : UserStartResponse.STATUS_ANDROID_FAILURE); 476 } 477 super.onCompleted(response); 478 } 479 }; 480 mService.startUser(request, callbackImpl); 481 } catch (SecurityException e) { 482 Log.e(TAG, "startUser(userId=" + userId + ", displayId=" + displayId + ")", e); 483 throw e; 484 } catch (RemoteException | RuntimeException e) { 485 UserStartResponse response = handleExceptionFromCarService(e, 486 new UserStartResponse(UserStartResponse.STATUS_ANDROID_FAILURE)); 487 callback.onResult(response); 488 } 489 } 490 491 /** 492 * Stops the specified user. 493 * 494 * @hide 495 */ 496 @SystemApi 497 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 498 android.Manifest.permission.INTERACT_ACROSS_USERS}) 499 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 500 minPlatformVersion = ApiRequirements.PlatformVersion.UPSIDE_DOWN_CAKE_0) stopUser(@onNull UserStopRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserStopResponse> callback)501 public void stopUser(@NonNull UserStopRequest request, 502 @NonNull @CallbackExecutor Executor executor, 503 @NonNull ResultCallback<UserStopResponse> callback) { 504 assertPlatformVersionAtLeastU(); 505 int uid = myUid(); 506 int userId = request.getUserHandle().getIdentifier(); 507 if (isPlatformVersionAtLeastU()) { 508 EventLogHelper.writeCarUserManagerStopUserReq(uid, userId); 509 } 510 try { 511 ResultCallbackImpl<UserStopResponse> callbackImpl = new ResultCallbackImpl<>( 512 executor, callback) { 513 @Override 514 protected void onCompleted(UserStopResponse response) { 515 if (isPlatformVersionAtLeastU()) { 516 EventLogHelper.writeCarUserManagerStopUserResp(uid, userId, 517 response != null ? response.getStatus() 518 : UserStopResponse.STATUS_ANDROID_FAILURE); 519 } 520 super.onCompleted(response); 521 } 522 }; 523 mService.stopUser(request, callbackImpl); 524 } catch (SecurityException e) { 525 Log.e(TAG, "stopUser(userId=" + userId + ")", e); 526 throw e; 527 } catch (RemoteException | RuntimeException e) { 528 UserStopResponse response = handleExceptionFromCarService(e, 529 new UserStopResponse(UserStopResponse.STATUS_ANDROID_FAILURE)); 530 callback.onResult(response); 531 } 532 } 533 534 // TODO(b/235991826): Add CTS test. 535 /** 536 * Switches the foreground user to the given user. 537 * 538 * @param userSwitchRequest contains target user. 539 * @param executor to execute the callback. 540 * @param callback called with the {code UserSwitchResult} 541 * 542 * @hide 543 */ 544 @SystemApi 545 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 546 android.Manifest.permission.CREATE_USERS}) 547 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 548 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) switchUser(@onNull UserSwitchRequest userSwitchRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserSwitchResult> callback)549 public void switchUser(@NonNull UserSwitchRequest userSwitchRequest, 550 @NonNull @CallbackExecutor Executor executor, 551 @NonNull ResultCallback<UserSwitchResult> callback) { 552 int uid = myUid(); 553 int targetUserId = userSwitchRequest.getUserHandle().getIdentifier(); 554 555 try { 556 ResultCallbackImpl<UserSwitchResult> resultCallbackImpl = new ResultCallbackImpl<>( 557 executor, callback) { 558 @Override 559 protected void onCompleted(UserSwitchResult result) { 560 if (result == null) { 561 EventLogHelper.writeCarUserManagerSwitchUserResp(uid, 562 UserSwitchResult.STATUS_ANDROID_FAILURE, /* errorMessage=*/ null); 563 } else { 564 EventLogHelper.writeCarUserManagerSwitchUserResp(uid, result.getStatus(), 565 result.getErrorMessage()); 566 } 567 super.onCompleted(result); 568 } 569 }; 570 EventLogHelper.writeCarUserManagerSwitchUserReq(uid, targetUserId); 571 mService.switchUser(targetUserId, HAL_TIMEOUT_MS, resultCallbackImpl); 572 } catch (SecurityException e) { 573 Log.w(TAG, "switchUser(" + targetUserId + ") failed: " + e); 574 throw e; 575 } catch (RemoteException | RuntimeException e) { 576 UserSwitchResult result = handleExceptionFromCarService(e, 577 new UserSwitchResult(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE, null)); 578 callback.onResult(result); 579 } 580 } 581 582 /** 583 * Switches the foreground user to the given target user. 584 * 585 * @hide 586 * @deprecated Use {@link #switchUser(UserSwitchRequest, Executor, ResultCallback)} instead. 587 */ 588 @TestApi 589 @Deprecated 590 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 591 android.Manifest.permission.CREATE_USERS}) 592 @AddedInOrBefore(majorVersion = 33, softRemovalVersion = 35, hardRemovalVersion = 37) switchUser(@serIdInt int targetUserId)593 public AsyncFuture<UserSwitchResult> switchUser(@UserIdInt int targetUserId) { 594 UserSwitchRequest userSwitchRequest = new UserSwitchRequest.Builder( 595 UserHandle.of(targetUserId)).build(); 596 AndroidFuture<UserSwitchResult> future = new AndroidFuture<>(); 597 switchUser(userSwitchRequest, Runnable::run, future::complete); 598 return new AndroidAsyncFuture<>(future); 599 } 600 601 /** 602 * Logouts the current user (if it was switched to by a device admin). 603 * 604 * @hide 605 */ 606 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 607 android.Manifest.permission.CREATE_USERS}) 608 @AddedInOrBefore(majorVersion = 33) logoutUser()609 public AsyncFuture<UserSwitchResult> logoutUser() { 610 int uid = myUid(); 611 try { 612 AndroidFuture<UserSwitchResult> future = new AndroidFuture<>(); 613 ResultCallbackImpl<UserSwitchResult> resultCallbackImpl = new ResultCallbackImpl<>( 614 Runnable::run, new SyncResultCallback<>()) { 615 @Override 616 protected void onCompleted(UserSwitchResult result) { 617 if (result == null) { 618 EventLogHelper.writeCarUserManagerLogoutUserResp(uid, 619 UserSwitchResult.STATUS_ANDROID_FAILURE, /* errorMessage=*/ null); 620 } else { 621 EventLogHelper.writeCarUserManagerLogoutUserResp(uid, result.getStatus(), 622 result.getErrorMessage()); 623 } 624 future.complete(result); 625 super.onCompleted(result); 626 } 627 }; 628 EventLogHelper.writeCarUserManagerLogoutUserReq(uid); 629 mService.logoutUser(HAL_TIMEOUT_MS, resultCallbackImpl); 630 return new AndroidAsyncFuture<>(future); 631 } catch (SecurityException e) { 632 throw e; 633 } catch (RemoteException | RuntimeException e) { 634 AsyncFuture<UserSwitchResult> future = 635 newSwitchResultForFailure(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE); 636 return handleExceptionFromCarService(e, future); 637 } 638 } 639 newSwitchResultForFailure( @serSwitchResult.Status int status)640 private AndroidAsyncFuture<UserSwitchResult> newSwitchResultForFailure( 641 @UserSwitchResult.Status int status) { 642 AndroidFuture<UserSwitchResult> future = new AndroidFuture<>(); 643 future.complete(new UserSwitchResult(status, null)); 644 return new AndroidAsyncFuture<>(future); 645 } 646 647 /** 648 * Creates a new guest Android user. 649 * 650 * @hide 651 * @deprecated Use {@link #createUser(UserCreationRequest, Executor, ResultCallback)} instead. 652 */ 653 @Deprecated 654 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 655 android.Manifest.permission.CREATE_USERS}) 656 @AddedInOrBefore(majorVersion = 33, softRemovalVersion = 35, hardRemovalVersion = 37) createGuest(@ullable String name)657 public AsyncFuture<UserCreationResult> createGuest(@Nullable String name) { 658 AndroidFuture<UserCreationResult> future = new AndroidFuture<>(); 659 UserCreationRequest.Builder userCreationRequestBuilder = new UserCreationRequest.Builder(); 660 if (name != null) { 661 userCreationRequestBuilder.setName(name); 662 } 663 createUser(userCreationRequestBuilder.setGuest().build(), Runnable::run, future::complete); 664 return new AndroidAsyncFuture<>(future); 665 } 666 667 /** 668 * Creates a new Android user. 669 * 670 * @hide 671 * @deprecated Use {@link #createUser(UserCreationRequest, Executor, ResultCallback)} instead. 672 */ 673 @Deprecated 674 @AddedInOrBefore(majorVersion = 33, softRemovalVersion = 35, hardRemovalVersion = 37) 675 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 676 android.Manifest.permission.CREATE_USERS}) createUser(@ullable String name, int flags)677 public AsyncFuture<UserCreationResult> createUser(@Nullable String name, 678 int flags) { 679 AndroidFuture<UserCreationResult> future = new AndroidFuture<>(); 680 UserCreationRequest.Builder userCreationRequestBuilder = new UserCreationRequest.Builder(); 681 if (name != null) { 682 userCreationRequestBuilder.setName(name); 683 } 684 685 if ((flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) { 686 userCreationRequestBuilder.setAdmin(); 687 } 688 689 if ((flags & UserManagerHelper.FLAG_EPHEMERAL) == UserManagerHelper.FLAG_EPHEMERAL) { 690 userCreationRequestBuilder.setEphemeral(); 691 } 692 693 createUser(userCreationRequestBuilder.build(), Runnable::run, future::complete); 694 return new AndroidAsyncFuture<>(future); 695 } 696 697 /** 698 * Creates a new Android user. 699 * 700 * @param userCreationRequest contains new user information 701 * @param executor to execute the callback. 702 * @param callback called with the {code UserCreationResult} 703 * @hide 704 */ 705 @SystemApi 706 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 707 android.Manifest.permission.CREATE_USERS}) 708 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 709 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) createUser(@onNull UserCreationRequest userCreationRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserCreationResult> callback)710 public void createUser(@NonNull UserCreationRequest userCreationRequest, 711 @NonNull @CallbackExecutor Executor executor, 712 @NonNull ResultCallback<UserCreationResult> callback) { 713 Objects.requireNonNull(userCreationRequest, "userCreationRequest cannot be null"); 714 Objects.requireNonNull(executor, "executor cannot be null"); 715 Objects.requireNonNull(callback, "callback cannot be null"); 716 int uid = myUid(); 717 try { 718 ResultCallbackImpl<UserCreationResult> resultCallbackImpl = 719 new ResultCallbackImpl<UserCreationResult>( 720 executor, callback) { 721 @Override 722 protected void onCompleted(UserCreationResult result) { 723 if (result == null) { 724 EventLogHelper.writeCarUserManagerCreateUserResp(uid, 725 UserCreationResult.STATUS_ANDROID_FAILURE, /* errorMessage=*/ null); 726 } else { 727 EventLogHelper.writeCarUserManagerCreateUserResp(uid, result.getStatus(), 728 result.getErrorMessage()); 729 } 730 super.onCompleted(result); 731 } 732 }; 733 String name = userCreationRequest.getName(); 734 String userType = userCreationRequest.isGuest() ? UserManager.USER_TYPE_FULL_GUEST 735 : UserManager.USER_TYPE_FULL_SECONDARY; 736 int flags = 0; 737 flags |= userCreationRequest.isAdmin() ? UserManagerHelper.FLAG_ADMIN : 0; 738 flags |= userCreationRequest.isEphemeral() ? UserManagerHelper.FLAG_EPHEMERAL : 0; 739 740 EventLogHelper.writeCarUserManagerCreateUserReq(uid, 741 UserHelperLite.safeName(name), userType, flags); 742 mService.createUser(userCreationRequest, HAL_TIMEOUT_MS, resultCallbackImpl); 743 System.out.println("manager test API replied"); 744 } catch (SecurityException e) { 745 throw e; 746 } catch (RemoteException | RuntimeException e) { 747 callback.onResult( 748 new UserCreationResult(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE)); 749 handleExceptionFromCarService(e, null); 750 } 751 } 752 753 /** 754 * Updates pre-created users. 755 * 756 * @deprecated Pre-created users are no longer supported. 757 * This method is no-op and will be removed soon. 758 * 759 * @hide 760 */ 761 @Deprecated 762 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 763 android.Manifest.permission.CREATE_USERS}) 764 @AddedInOrBefore(majorVersion = 33) updatePreCreatedUsers()765 public void updatePreCreatedUsers() { 766 Log.w(TAG, "updatePreCreatedUsers(): This method should not be called." 767 + " Pre-created users are no longer supported."); 768 } 769 770 771 /** 772 * Removes the given user. 773 * 774 * @param userRemovalRequest contains user to be removed. 775 * @param executor to execute the callback. 776 * @param callback called with the {code UserRemovalResult} 777 * 778 * @hide 779 */ 780 @SystemApi 781 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 782 android.Manifest.permission.CREATE_USERS}) 783 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 784 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) removeUser(@onNull UserRemovalRequest userRemovalRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserRemovalResult> callback)785 public void removeUser(@NonNull UserRemovalRequest userRemovalRequest, 786 @NonNull @CallbackExecutor Executor executor, 787 @NonNull ResultCallback<UserRemovalResult> callback) { 788 int uid = myUid(); 789 EventLogHelper.writeCarUserManagerRemoveUserReq(uid, 790 userRemovalRequest.getUserHandle().getIdentifier()); 791 try { 792 ResultCallbackImpl<UserRemovalResult> resultCallbackImpl = new ResultCallbackImpl<>( 793 executor, callback) { 794 @Override 795 protected void onCompleted(UserRemovalResult result) { 796 EventLogHelper.writeCarUserManagerRemoveUserResp(uid, 797 result != null ? result.getStatus() 798 : UserRemovalResult.STATUS_ANDROID_FAILURE); 799 super.onCompleted(result); 800 } 801 }; 802 mService.removeUser(userRemovalRequest.getUserHandle().getIdentifier(), 803 resultCallbackImpl); 804 } catch (SecurityException e) { 805 Log.e(TAG, "CarUserManager removeUser", e); 806 throw e; 807 } catch (RemoteException | RuntimeException e) { 808 UserRemovalResult result = handleExceptionFromCarService(e, 809 new UserRemovalResult(UserRemovalResult.STATUS_ANDROID_FAILURE)); 810 callback.onResult(result); 811 } 812 } 813 814 /** 815 * Removes the given user. 816 * 817 * @param userId identification of the user to be removed. 818 * 819 * @return whether the user was successfully removed. 820 * 821 * @hide 822 * 823 * @deprecated use {@link #removeUser(UserRemovalRequest, Executor, ResultCallback)} instead. 824 * It will be marked removed in {@code V} and hard removed in {@code X}. 825 */ 826 @Deprecated 827 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 828 android.Manifest.permission.CREATE_USERS}) 829 @NonNull 830 @AddedInOrBefore(majorVersion = 33) removeUser(@serIdInt int userId)831 public UserRemovalResult removeUser(@UserIdInt int userId) { 832 UserRemovalRequest userRemovalRequest = new UserRemovalRequest.Builder( 833 UserHandle.of(userId)).build(); 834 SyncResultCallback<UserRemovalResult> userRemovalResultCallback = 835 new SyncResultCallback<>(); 836 837 removeUser(userRemovalRequest, Runnable::run, userRemovalResultCallback); 838 839 UserRemovalResult userRemovalResult = new UserRemovalResult( 840 UserRemovalResult.STATUS_ANDROID_FAILURE); 841 842 try { 843 userRemovalResult = userRemovalResultCallback.get(USER_CALL_TIMEOUT_MS, 844 TimeUnit.MILLISECONDS); 845 } catch (TimeoutException e) { 846 Log.e(TAG, "CarUserManager removeUser(" + userId + "): ", e); 847 } catch (InterruptedException e) { 848 Thread.currentThread().interrupt(); 849 Log.e(TAG, "CarUserManager removeUser(" + userId + "): ", e); 850 } 851 852 return userRemovalResult; 853 } 854 855 /** 856 * Adds a listener for {@link UserLifecycleEvent user lifecycle events}. 857 * 858 * @throws IllegalStateException if the listener was already added. 859 * 860 * @hide 861 */ 862 @SystemApi 863 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) 864 @AddedInOrBefore(majorVersion = 33) addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleListener listener)865 public void addListener(@NonNull @CallbackExecutor Executor executor, 866 @NonNull UserLifecycleListener listener) { 867 addListenerInternal(executor, /* filter= */null, listener); 868 } 869 870 /** 871 * Adds a listener for {@link UserLifecycleEvent user lifecycle events} with a filter that can 872 * specify a specific event type or a user id. 873 * 874 * @throws IllegalStateException if the listener was already added. 875 * 876 * @hide 877 */ 878 @SystemApi 879 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) 880 @AddedInOrBefore(majorVersion = 33) addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener)881 public void addListener(@NonNull @CallbackExecutor Executor executor, 882 @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener) { 883 Objects.requireNonNull(filter, "filter cannot be null"); 884 885 addListenerInternal(executor, filter, listener); 886 } 887 addListenerInternal(@allbackExecutor Executor executor, @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener)888 private void addListenerInternal(@CallbackExecutor Executor executor, 889 @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener) { 890 Objects.requireNonNull(executor, "executor cannot be null"); 891 Objects.requireNonNull(listener, "listener cannot be null"); 892 893 int uid = myUid(); 894 String packageName = getContext().getPackageName(); 895 if (DBG) { 896 Log.d(TAG, "addListener(): uid=" + uid + ", pkg=" + packageName 897 + ", listener=" + listener + ", filter= " + filter); 898 } 899 synchronized (mLock) { 900 Preconditions.checkState(mListeners == null || !mListeners.containsKey(listener), 901 "already called for this listener"); 902 if (mReceiver == null) { 903 mReceiver = new LifecycleResultReceiver(); 904 if (DBG) { 905 Log.d(TAG, "Setting lifecycle receiver with filter " + filter 906 + " for uid " + uid + " and package " + packageName); 907 } 908 } else { 909 if (DBG) { 910 Log.d(TAG, "Already set receiver for uid " + uid + " and package " 911 + packageName + " adding new filter " + filter); 912 } 913 } 914 try { 915 boolean hasFilter = filter != null; 916 EventLogHelper.writeCarUserManagerAddListener(uid, packageName, hasFilter); 917 mService.setLifecycleListenerForApp(packageName, filter, mReceiver); 918 } catch (RemoteException e) { 919 handleRemoteExceptionFromCarService(e); 920 } 921 922 if (mListeners == null) { 923 mListeners = new ArrayMap<>(1); // Most likely app will have just one listener 924 } else if (DBG) { 925 Log.d(TAG, "addListener(" + getLambdaName(listener) + "): context " + getContext() 926 + " already has " + mListeners.size() + " listeners: " 927 + mListeners.keySet().stream() 928 .map((l) -> getLambdaName(l)) 929 .collect(Collectors.toList()), new Exception("caller's stack")); 930 } 931 if (DBG) Log.d(TAG, "Adding listener: " + listener + " with filter " + filter); 932 mListeners.put(listener, Pair.create(filter, executor)); 933 } 934 } 935 936 /** 937 * Removes a listener for {@link UserLifecycleEvent user lifecycle events}. 938 * 939 * @throws IllegalStateException if the listener was not added beforehand. 940 * 941 * @hide 942 */ 943 @SystemApi 944 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) 945 @AddedInOrBefore(majorVersion = 33) removeListener(@onNull UserLifecycleListener listener)946 public void removeListener(@NonNull UserLifecycleListener listener) { 947 Objects.requireNonNull(listener, "listener cannot be null"); 948 949 int uid = myUid(); 950 String packageName = getContext().getPackageName(); 951 if (DBG) { 952 Log.d(TAG, "removeListener(): uid=" + uid + ", pkg=" + packageName 953 + ", listener=" + listener); 954 } 955 synchronized (mLock) { 956 Preconditions.checkState(mListeners != null && mListeners.containsKey(listener), 957 "not called for this listener yet"); 958 mListeners.remove(listener); 959 960 // Note that there can be some rare corner cases that a listener is removed but its 961 // corresponding filter remains in the service side. This may cause slight inefficiency 962 // due to unnecessary receiver calls. It will still be functionally correct, because the 963 // removed listener will no longer be invoked. 964 if (!mListeners.isEmpty()) { 965 if (DBG) Log.d(TAG, "removeListeners(): still " + mListeners.size() + " left"); 966 return; 967 } 968 mListeners = null; 969 970 if (mReceiver == null) { 971 Log.wtf(TAG, "removeListener(): receiver already null"); 972 return; 973 } 974 975 EventLogHelper.writeCarUserManagerRemoveListener(uid, packageName); 976 if (DBG) { 977 Log.d(TAG, "Removing lifecycle receiver for uid=" + uid + " and package " 978 + packageName); 979 } 980 try { 981 mService.resetLifecycleListenerForApp(mReceiver); 982 mReceiver = null; 983 } catch (RemoteException e) { 984 handleRemoteExceptionFromCarService(e); 985 } 986 } 987 } 988 989 /** 990 * Check if user hal supports user association. 991 * 992 * @hide 993 */ 994 @AddedInOrBefore(majorVersion = 33) isUserHalUserAssociationSupported()995 public boolean isUserHalUserAssociationSupported() { 996 try { 997 return mService.isUserHalUserAssociationSupported(); 998 } catch (RemoteException | RuntimeException e) { 999 return handleExceptionFromCarService(e, false); 1000 } 1001 } 1002 1003 /** 1004 * Gets the user authentication types associated with this manager's user. 1005 * 1006 * @hide 1007 */ 1008 @NonNull 1009 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 1010 android.Manifest.permission.CREATE_USERS}) 1011 @AddedInOrBefore(majorVersion = 33) getUserIdentificationAssociation( @serIdentificationAssociationType int... types)1012 public UserIdentificationAssociationResponse getUserIdentificationAssociation( 1013 @UserIdentificationAssociationType int... types) { 1014 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 1015 EventLogHelper.writeCarUserManagerGetUserAuthReq(convertToObjectArray(types)); 1016 try { 1017 UserIdentificationAssociationResponse response = 1018 mService.getUserIdentificationAssociation(types); 1019 if (response != null) { 1020 int[] values = response.getValues(); 1021 EventLogHelper.writeCarUserManagerGetUserAuthResp(convertToObjectArray(values)); 1022 } 1023 return response; 1024 } catch (SecurityException e) { 1025 throw e; 1026 } catch (RemoteException | RuntimeException e) { 1027 return handleExceptionFromCarService(e, 1028 UserIdentificationAssociationResponse.forFailure(e.getMessage())); 1029 } 1030 } 1031 1032 @Nullable convertToObjectArray(int[] input)1033 private Object[] convertToObjectArray(int[] input) { 1034 if (input == null) return null; 1035 Object[] output = new Object[input.length]; 1036 for (int i = 0; i < input.length; i++) { 1037 output[i] = input[i]; 1038 } 1039 return output; 1040 } 1041 1042 /** 1043 * Sets the user authentication types associated with this manager's user. 1044 * 1045 * @hide 1046 */ 1047 @NonNull 1048 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 1049 android.Manifest.permission.CREATE_USERS}) 1050 @AddedInOrBefore(majorVersion = 33) setUserIdentificationAssociation( @serIdentificationAssociationType int[] types, @UserIdentificationAssociationSetValue int[] values)1051 public AsyncFuture<UserIdentificationAssociationResponse> setUserIdentificationAssociation( 1052 @UserIdentificationAssociationType int[] types, 1053 @UserIdentificationAssociationSetValue int[] values) { 1054 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 1055 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value"); 1056 if (types.length != values.length) { 1057 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values (" 1058 + Arrays.toString(values) + ") should have the same length"); 1059 } 1060 // TODO(b/153900032): move this logic to a common helper 1061 Object[] loggedValues = new Integer[types.length * 2]; 1062 for (int i = 0; i < types.length; i++) { 1063 loggedValues[i * 2] = types[i]; 1064 loggedValues[i * 2 + 1 ] = values[i]; 1065 } 1066 EventLogHelper.writeCarUserManagerSetUserAuthReq(loggedValues); 1067 1068 try { 1069 AndroidFuture<UserIdentificationAssociationResponse> future = 1070 new AndroidFuture<UserIdentificationAssociationResponse>() { 1071 @Override 1072 protected void onCompleted(UserIdentificationAssociationResponse result, 1073 Throwable err) { 1074 if (result != null) { 1075 int[] rawValues = result.getValues(); 1076 // TODO(b/153900032): move this logic to a common helper 1077 if (rawValues != null) { 1078 Object[] loggedValues = new Object[rawValues.length]; 1079 for (int i = 0; i < rawValues.length; i++) { 1080 loggedValues[i] = rawValues[i]; 1081 } 1082 EventLogHelper.writeCarUserManagerSetUserAuthResp(loggedValues); 1083 } 1084 } else { 1085 Log.w(TAG, "setUserIdentificationAssociation(" + Arrays.toString(types) 1086 + ", " + Arrays.toString(values) + ") failed: " + err); 1087 } 1088 super.onCompleted(result, err); 1089 }; 1090 }; 1091 mService.setUserIdentificationAssociation(HAL_TIMEOUT_MS, types, values, future); 1092 return new AndroidAsyncFuture<>(future); 1093 } catch (SecurityException e) { 1094 throw e; 1095 } catch (RemoteException | RuntimeException e) { 1096 AndroidFuture<UserIdentificationAssociationResponse> future = new AndroidFuture<>(); 1097 future.complete(UserIdentificationAssociationResponse.forFailure()); 1098 return handleExceptionFromCarService(e, new AndroidAsyncFuture<>(future)); 1099 } 1100 } 1101 1102 /** 1103 * Sets a callback to be notified before user switch. It should only be used by Car System UI. 1104 * 1105 * @hide 1106 * @deprecated use {@link #setUserSwitchUiCallback(Executor, UserHandleSwitchUiCallback)} 1107 * instead. 1108 */ 1109 @Deprecated 1110 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) 1111 @AddedInOrBefore(majorVersion = 33, softRemovalVersion = 35, hardRemovalVersion = 37) setUserSwitchUiCallback(@onNull UserSwitchUiCallback callback)1112 public void setUserSwitchUiCallback(@NonNull UserSwitchUiCallback callback) { 1113 Preconditions.checkArgument(callback != null, "Null callback"); 1114 UserHandleSwitchUiCallback userHandleSwitchUiCallback = (userHandle) -> { 1115 callback.showUserSwitchDialog(userHandle.getIdentifier()); 1116 }; 1117 setUserSwitchUiCallback(Runnable::run, userHandleSwitchUiCallback); 1118 } 1119 1120 /** 1121 * Sets a callback to be notified before user switch. 1122 * 1123 * <p> It should only be used by Car System UI. Setting this callback will notify the Car 1124 * System UI to show the user switching dialog. 1125 * 1126 * @hide 1127 */ 1128 @SystemApi 1129 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) 1130 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 1131 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) setUserSwitchUiCallback(@onNull @allbackExecutor Executor executor, @NonNull UserHandleSwitchUiCallback callback)1132 public void setUserSwitchUiCallback(@NonNull @CallbackExecutor Executor executor, 1133 @NonNull UserHandleSwitchUiCallback callback) { 1134 Preconditions.checkArgument(callback != null, "Null callback"); 1135 UserSwitchUiCallbackReceiver userSwitchUiCallbackReceiver = 1136 new UserSwitchUiCallbackReceiver(callback); 1137 try { 1138 mService.setUserSwitchUiCallback(userSwitchUiCallbackReceiver); 1139 } catch (RemoteException e) { 1140 handleRemoteExceptionFromCarService(e); 1141 } 1142 } 1143 1144 // TODO(b/154958003): use mReceiver instead as now there are two binder objects 1145 /** 1146 * {@code ICarResultReceiver} used to receive user switch UI Callback. 1147 */ 1148 private final class UserSwitchUiCallbackReceiver extends ICarResultReceiver.Stub { 1149 1150 private final UserHandleSwitchUiCallback mUserHandleSwitchUiCallback; 1151 UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback)1152 UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback) { 1153 mUserHandleSwitchUiCallback = callback; 1154 } 1155 1156 @Override send(int userId, Bundle unused)1157 public void send(int userId, Bundle unused) throws RemoteException { 1158 mUserHandleSwitchUiCallback.onUserSwitchStart(UserHandle.of(userId)); 1159 } 1160 } 1161 1162 /** 1163 * {@code ICarResultReceiver} used to receive lifecycle events and dispatch to the proper 1164 * listener. 1165 */ 1166 private class LifecycleResultReceiver extends ICarResultReceiver.Stub { 1167 @Override send(int resultCode, Bundle resultData)1168 public void send(int resultCode, Bundle resultData) { 1169 if (resultData == null) { 1170 Log.w(TAG, "Received result (" + resultCode + ") without data"); 1171 return; 1172 } 1173 int from = resultData.getInt(BUNDLE_PARAM_PREVIOUS_USER_ID, 1174 UserManagerHelper.USER_NULL); 1175 int to = resultCode; 1176 int eventType = resultData.getInt(BUNDLE_PARAM_ACTION); 1177 UserLifecycleEvent event = new UserLifecycleEvent(eventType, from, to); 1178 ArrayMap<UserLifecycleListener, Pair<UserLifecycleEventFilter, Executor>> listeners; 1179 synchronized (mLock) { 1180 if (mListeners == null) { 1181 Log.w(TAG, "No listeners for event " + event); 1182 return; 1183 } 1184 listeners = new ArrayMap<>(mListeners); 1185 } 1186 int size = listeners.size(); 1187 EventLogHelper.writeCarUserManagerNotifyLifecycleListener(size, eventType, from, to); 1188 for (int i = 0; i < size; i++) { 1189 UserLifecycleListener listener = listeners.keyAt(i); 1190 UserLifecycleEventFilter filter = listeners.valueAt(i).first; 1191 if (filter != null && !filter.apply(event)) { 1192 if (DBG) { 1193 Log.d(TAG, "Listener " + getLambdaName(listener) 1194 + " is skipped for the event " + event + " due to the filter " 1195 + filter); 1196 } 1197 continue; 1198 } 1199 Executor executor = listeners.valueAt(i).second; 1200 if (DBG) { 1201 Log.d(TAG, "Calling " + getLambdaName(listener) + " for event " + event); 1202 } 1203 executor.execute(() -> listener.onEvent(event)); 1204 } 1205 mNumberReceivedEvents++; 1206 if (VERBOSE) { 1207 if (mEvents == null) { 1208 mEvents = new ArrayList<>(); 1209 } 1210 mEvents.add(event); 1211 } 1212 } 1213 } 1214 1215 /** @hide */ 1216 @Override 1217 @AddedInOrBefore(majorVersion = 33) onCarDisconnected()1218 public void onCarDisconnected() { 1219 // nothing to do 1220 } 1221 1222 private final class Dumper implements Dumpable { 1223 @Override dump(PrintWriter pw, String[] args)1224 public void dump(PrintWriter pw, String[] args) { 1225 String prefix = " "; 1226 1227 pw.printf("DBG=%b, VERBOSE=%b\n", DBG, VERBOSE); 1228 int listenersSize = 0; 1229 synchronized (mLock) { 1230 pw.printf("mReceiver: %s\n", mReceiver); 1231 if (mListeners == null) { 1232 pw.println("no listeners"); 1233 } else { 1234 listenersSize = mListeners.size(); 1235 pw.printf("%d listeners\n", listenersSize); 1236 } 1237 if (DBG) { 1238 for (int i = 0; i < listenersSize; i++) { 1239 pw.printf("%s%d: %s\n", prefix, i + 1, mListeners.keyAt(i)); 1240 } 1241 } 1242 } 1243 pw.printf("mNumberReceivedEvents: %d\n", mNumberReceivedEvents); 1244 if (VERBOSE && mEvents != null) { 1245 for (int i = 0; i < mEvents.size(); i++) { 1246 pw.printf("%s%d: %s\n", prefix, i + 1, mEvents.get(i)); 1247 } 1248 } 1249 } 1250 1251 @Override getDumpableName()1252 public String getDumpableName() { 1253 return CarUserManager.class.getSimpleName(); 1254 } 1255 } 1256 1257 /** 1258 * @hide 1259 */ 1260 @SystemApi 1261 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 1262 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 1263 @NonNull lifecycleEventTypeToString(@serLifecycleEventType int type)1264 public static String lifecycleEventTypeToString(@UserLifecycleEventType int type) { 1265 switch (type) { 1266 case USER_LIFECYCLE_EVENT_TYPE_STARTING: 1267 return "STARTING"; 1268 case USER_LIFECYCLE_EVENT_TYPE_SWITCHING: 1269 return "SWITCHING"; 1270 case USER_LIFECYCLE_EVENT_TYPE_UNLOCKING: 1271 return "UNLOCKING"; 1272 case USER_LIFECYCLE_EVENT_TYPE_UNLOCKED: 1273 return "UNLOCKED"; 1274 case USER_LIFECYCLE_EVENT_TYPE_STOPPING: 1275 return "STOPPING"; 1276 case USER_LIFECYCLE_EVENT_TYPE_STOPPED: 1277 return "STOPPED"; 1278 case USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED: 1279 return "POST_UNLOCKED"; 1280 case USER_LIFECYCLE_EVENT_TYPE_CREATED: 1281 return "CREATED"; 1282 case USER_LIFECYCLE_EVENT_TYPE_REMOVED: 1283 return "REMOVED"; 1284 case USER_LIFECYCLE_EVENT_TYPE_VISIBLE: 1285 return "VISIBLE"; 1286 case USER_LIFECYCLE_EVENT_TYPE_INVISIBLE: 1287 return "INVISIBLE"; 1288 default: 1289 return "UNKNOWN-" + type; 1290 } 1291 } 1292 1293 /** 1294 * Checks if the given {@code userId} represents a valid user. 1295 * 1296 * <p>A "valid" user: 1297 * 1298 * <ul> 1299 * <li>Must exist in the device. 1300 * <li>Is not in the process of being deleted. 1301 * <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use 1302 * {@link UserManager#isHeadlessSystemUserMode() headless system user mode}. 1303 * </ul> 1304 * 1305 * @hide 1306 * @deprecated use {@link #isValidUser(UserHandle)} instead. 1307 */ 1308 @Deprecated 1309 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 1310 android.Manifest.permission.CREATE_USERS}) 1311 @AddedInOrBefore(majorVersion = 33, softRemovalVersion = 35, hardRemovalVersion = 37) isValidUser(@serIdInt int userId)1312 public boolean isValidUser(@UserIdInt int userId) { 1313 return isValidUser(UserHandle.of(userId)); 1314 } 1315 1316 /** 1317 * Checks if the given {@code userHandle} represents a valid user. 1318 * 1319 * <p>A "valid" user: 1320 * 1321 * <ul> 1322 * <li>Must exist in the device. 1323 * <li>Is not in the process of being deleted. 1324 * <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use 1325 * {@link UserManager#isHeadlessSystemUserMode() headless system user mode}. 1326 * </ul> 1327 * 1328 */ 1329 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 1330 android.Manifest.permission.CREATE_USERS}) 1331 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 1332 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 1333 @SuppressWarnings("UserHandle") isValidUser(@onNull UserHandle userHandle)1334 public boolean isValidUser(@NonNull UserHandle userHandle) { 1335 List<UserHandle> allUsers = mUserManager.getUserHandles(/* excludeDying=*/ true); 1336 for (int i = 0; i < allUsers.size(); i++) { 1337 UserHandle user = allUsers.get(i); 1338 if (user.equals(userHandle) && (!userHandle.equals(UserHandle.SYSTEM) 1339 || !UserManager.isHeadlessSystemUserMode())) { 1340 return true; 1341 } 1342 } 1343 return false; 1344 } 1345 1346 /** 1347 * Defines a lifecycle event for an Android user. 1348 * 1349 * @hide 1350 */ 1351 @SystemApi 1352 public static final class UserLifecycleEvent { 1353 private final @UserLifecycleEventType int mEventType; 1354 private final @UserIdInt int mUserId; 1355 private final @UserIdInt int mPreviousUserId; 1356 1357 /** @hide */ UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int from, @UserIdInt int to)1358 public UserLifecycleEvent(@UserLifecycleEventType int eventType, 1359 @UserIdInt int from, @UserIdInt int to) { 1360 mEventType = eventType; 1361 mPreviousUserId = from; 1362 mUserId = to; 1363 } 1364 1365 /** @hide */ UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int to)1366 public UserLifecycleEvent(@UserLifecycleEventType int eventType, @UserIdInt int to) { 1367 this(eventType, UserManagerHelper.USER_NULL, to); 1368 } 1369 1370 /** 1371 * Gets the event type. 1372 * 1373 * @return either {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STARTING}, 1374 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}, 1375 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKING}, 1376 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKED}, 1377 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPING} or 1378 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPED} for all apps; 1379 * for apps {@link CarPackageManager#getTargetCarVersion() targeting car version} 1380 * {@link CarVersion.VERSION_CODES#TIRAMISU_1} or higher, it could be new types 1381 * added on later releases, such as 1382 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_CREATED}, 1383 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_REMOVED} and possibly others. 1384 * 1385 */ 1386 @UserLifecycleEventType 1387 @AddedInOrBefore(majorVersion = 33) getEventType()1388 public int getEventType() { 1389 return mEventType; 1390 } 1391 1392 /** 1393 * Gets the id of the user whose event is being reported. 1394 * 1395 * @hide 1396 */ 1397 @UserIdInt 1398 @AddedInOrBefore(majorVersion = 33) getUserId()1399 public int getUserId() { 1400 return mUserId; 1401 } 1402 1403 /** 1404 * Gets the handle of the user whose event is being reported. 1405 */ 1406 @NonNull 1407 @AddedInOrBefore(majorVersion = 33) getUserHandle()1408 public UserHandle getUserHandle() { 1409 return UserHandle.of(mUserId); 1410 } 1411 1412 /** 1413 * Gets the id of the user being switched from. 1414 * 1415 * <p>This method returns {@link UserHandle#USER_NULL} for all event types but 1416 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}. 1417 * 1418 * @hide 1419 */ 1420 @UserIdInt 1421 @AddedInOrBefore(majorVersion = 33) getPreviousUserId()1422 public int getPreviousUserId() { 1423 return mPreviousUserId; 1424 } 1425 1426 /** 1427 * Gets the handle of the user being switched from. 1428 * 1429 * <p>This method returns {@code null} for all event types but 1430 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}. 1431 */ 1432 @Nullable 1433 @AddedInOrBefore(majorVersion = 33) getPreviousUserHandle()1434 public UserHandle getPreviousUserHandle() { 1435 return mPreviousUserId == UserManagerHelper.USER_NULL ? null 1436 : UserHandle.of(mPreviousUserId); 1437 } 1438 1439 @Override toString()1440 public String toString() { 1441 StringBuilder builder = new StringBuilder("Event[type=") 1442 .append(lifecycleEventTypeToString(mEventType)); 1443 if (mPreviousUserId != UserManagerHelper.USER_NULL) { 1444 builder 1445 .append(",from=").append(mPreviousUserId) 1446 .append(",to=").append(mUserId); 1447 } else { 1448 builder.append(",user=").append(mUserId); 1449 } 1450 1451 return builder.append(']').toString(); 1452 } 1453 1454 @Override equals(@ullable Object o)1455 public boolean equals(@Nullable Object o) { 1456 if (this == o) return true; 1457 if (o == null || getClass() != o.getClass()) return false; 1458 1459 UserLifecycleEvent that = (UserLifecycleEvent) o; 1460 return mEventType == that.mEventType && mUserId == that.mUserId 1461 && mPreviousUserId == that.mPreviousUserId; 1462 } 1463 1464 @Override hashCode()1465 public int hashCode() { 1466 int hash = 23; 1467 hash = 17 * hash + mEventType; 1468 hash = 17 * hash + mUserId; 1469 hash = 17 * hash + mPreviousUserId; 1470 1471 return hash; 1472 } 1473 } 1474 1475 /** 1476 * Listener for Android User lifecycle events. 1477 * 1478 * <p>Must be registered using {@link CarUserManager#addListener(UserLifecycleListener)} and 1479 * unregistered through {@link CarUserManager#removeListener(UserLifecycleListener)}. 1480 * 1481 * @hide 1482 */ 1483 @SystemApi 1484 public interface UserLifecycleListener { 1485 1486 /** 1487 * Called to notify the given {@code event}. 1488 */ 1489 @AddedInOrBefore(majorVersion = 33) onEvent(@onNull UserLifecycleEvent event)1490 void onEvent(@NonNull UserLifecycleEvent event); 1491 } 1492 1493 /** 1494 * Callback for notifying user switch before switch started. 1495 * 1496 * <p> It should only be used by Car System UI. The purpose of this callback is to notify the 1497 * Car System UI to display the user switch UI. 1498 * 1499 * @hide 1500 * @deprecated use {@link #UserHandleSwitchUiCallback} instead. 1501 */ 1502 @Deprecated 1503 public interface UserSwitchUiCallback { 1504 1505 /** 1506 * Called to notify that user switch dialog should be shown now. 1507 */ 1508 @AddedInOrBefore(majorVersion = 33) showUserSwitchDialog(@serIdInt int userId)1509 void showUserSwitchDialog(@UserIdInt int userId); 1510 } 1511 1512 /** 1513 * Callback for notifying user switch before switch started. 1514 * 1515 * @hide 1516 */ 1517 @SystemApi 1518 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 1519 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 1520 public interface UserHandleSwitchUiCallback { 1521 1522 /** 1523 * Called before the user switch starts. 1524 * 1525 * <p> This is typically used to show the user dialog. 1526 */ 1527 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0, 1528 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 1529 @SuppressWarnings("UserHandleName") onUserSwitchStart(@onNull UserHandle userHandle)1530 void onUserSwitchStart(@NonNull UserHandle userHandle); 1531 } 1532 } 1533