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