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 System.out.println("manager test API replied"); 726 } catch (SecurityException e) { 727 throw e; 728 } catch (RemoteException | RuntimeException e) { 729 callback.onResult( 730 new UserCreationResult(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE)); 731 handleExceptionFromCarService(e, null); 732 } 733 } 734 735 /** 736 * Updates pre-created users. 737 * 738 * @deprecated Pre-created users are no longer supported. 739 * This method is no-op and will be removed soon. 740 * 741 * @hide 742 */ 743 @Deprecated 744 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 745 android.Manifest.permission.CREATE_USERS}) updatePreCreatedUsers()746 public void updatePreCreatedUsers() { 747 Slog.w(TAG, "updatePreCreatedUsers(): This method should not be called." 748 + " Pre-created users are no longer supported."); 749 } 750 751 752 /** 753 * Removes the given user. 754 * 755 * @param userRemovalRequest contains user to be removed. 756 * @param executor to execute the callback. 757 * @param callback called with the {code UserRemovalResult} 758 * 759 * @hide 760 */ 761 @SystemApi 762 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 763 android.Manifest.permission.CREATE_USERS}) removeUser(@onNull UserRemovalRequest userRemovalRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserRemovalResult> callback)764 public void removeUser(@NonNull UserRemovalRequest userRemovalRequest, 765 @NonNull @CallbackExecutor Executor executor, 766 @NonNull ResultCallback<UserRemovalResult> callback) { 767 int uid = myUid(); 768 EventLogHelper.writeCarUserManagerRemoveUserReq(uid, 769 userRemovalRequest.getUserHandle().getIdentifier()); 770 try { 771 ResultCallbackImpl<UserRemovalResult> resultCallbackImpl = new ResultCallbackImpl<>( 772 executor, callback) { 773 @Override 774 protected void onCompleted(UserRemovalResult result) { 775 EventLogHelper.writeCarUserManagerRemoveUserResp(uid, 776 result != null ? result.getStatus() 777 : UserRemovalResult.STATUS_ANDROID_FAILURE); 778 super.onCompleted(result); 779 } 780 }; 781 mService.removeUser(userRemovalRequest.getUserHandle().getIdentifier(), 782 resultCallbackImpl); 783 } catch (SecurityException e) { 784 Slog.e(TAG, "CarUserManager removeUser", e); 785 throw e; 786 } catch (RemoteException | RuntimeException e) { 787 UserRemovalResult result = handleExceptionFromCarService(e, 788 new UserRemovalResult(UserRemovalResult.STATUS_ANDROID_FAILURE)); 789 callback.onResult(result); 790 } 791 } 792 793 /** 794 * Removes the given user. 795 * 796 * @param userId identification of the user to be removed. 797 * 798 * @return whether the user was successfully removed. 799 * 800 * @hide 801 * 802 * @deprecated use {@link #removeUser(UserRemovalRequest, Executor, ResultCallback)} instead. 803 * It will be marked removed in {@code V} and hard removed in {@code X}. 804 */ 805 @Deprecated 806 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 807 android.Manifest.permission.CREATE_USERS}) 808 @NonNull removeUser(@serIdInt int userId)809 public UserRemovalResult removeUser(@UserIdInt int userId) { 810 UserRemovalRequest userRemovalRequest = new UserRemovalRequest.Builder( 811 UserHandle.of(userId)).build(); 812 SyncResultCallback<UserRemovalResult> userRemovalResultCallback = 813 new SyncResultCallback<>(); 814 815 removeUser(userRemovalRequest, Runnable::run, userRemovalResultCallback); 816 817 UserRemovalResult userRemovalResult = new UserRemovalResult( 818 UserRemovalResult.STATUS_ANDROID_FAILURE); 819 820 try { 821 userRemovalResult = userRemovalResultCallback.get(USER_CALL_TIMEOUT_MS, 822 TimeUnit.MILLISECONDS); 823 } catch (TimeoutException e) { 824 Slog.e(TAG, "CarUserManager removeUser(" + userId + "): ", e); 825 } catch (InterruptedException e) { 826 Thread.currentThread().interrupt(); 827 Slog.e(TAG, "CarUserManager removeUser(" + userId + "): ", e); 828 } 829 830 return userRemovalResult; 831 } 832 833 /** 834 * Adds a listener for {@link UserLifecycleEvent user lifecycle events}. 835 * 836 * @throws IllegalStateException if the listener was already added. 837 * 838 * @hide 839 */ 840 @SystemApi 841 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleListener listener)842 public void addListener(@NonNull @CallbackExecutor Executor executor, 843 @NonNull UserLifecycleListener listener) { 844 addListenerInternal(executor, /* filter= */null, listener); 845 } 846 847 /** 848 * Adds a listener for {@link UserLifecycleEvent user lifecycle events} with a filter that can 849 * specify a specific event type or a user id. 850 * 851 * @throws IllegalStateException if the listener was already added. 852 * 853 * @hide 854 */ 855 @SystemApi 856 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener)857 public void addListener(@NonNull @CallbackExecutor Executor executor, 858 @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener) { 859 Objects.requireNonNull(filter, "filter cannot be null"); 860 861 addListenerInternal(executor, filter, listener); 862 } 863 addListenerInternal(@allbackExecutor Executor executor, @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener)864 private void addListenerInternal(@CallbackExecutor Executor executor, 865 @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener) { 866 Objects.requireNonNull(executor, "executor cannot be null"); 867 Objects.requireNonNull(listener, "listener cannot be null"); 868 869 int uid = myUid(); 870 String packageName = getContext().getPackageName(); 871 if (DBG) { 872 Slog.d(TAG, "addListener(): uid=" + uid + ", pkg=" + packageName 873 + ", listener=" + listener + ", filter= " + filter); 874 } 875 synchronized (mLock) { 876 Preconditions.checkState(mListeners == null || !mListeners.containsKey(listener), 877 "already called for this listener"); 878 if (mReceiver == null) { 879 mReceiver = new LifecycleResultReceiver(); 880 if (DBG) { 881 Slog.d(TAG, "Setting lifecycle receiver with filter " + filter 882 + " for uid " + uid + " and package " + packageName); 883 } 884 } else { 885 if (DBG) { 886 Slog.d(TAG, "Already set receiver for uid " + uid + " and package " 887 + packageName + " adding new filter " + filter); 888 } 889 } 890 try { 891 boolean hasFilter = filter != null; 892 EventLogHelper.writeCarUserManagerAddListener(uid, packageName, hasFilter); 893 mService.setLifecycleListenerForApp(packageName, filter, mReceiver); 894 } catch (RemoteException e) { 895 handleRemoteExceptionFromCarService(e); 896 } 897 898 if (mListeners == null) { 899 mListeners = new ArrayMap<>(1); // Most likely app will have just one listener 900 } else if (DBG) { 901 Slog.d(TAG, "addListener(" + getLambdaName(listener) + "): context " + getContext() 902 + " already has " + mListeners.size() + " listeners: " 903 + mListeners.keySet().stream() 904 .map((l) -> getLambdaName(l)) 905 .collect(Collectors.toList()), new Exception("caller's stack")); 906 } 907 if (DBG) Slog.d(TAG, "Adding listener: " + listener + " with filter " + filter); 908 mListeners.put(listener, Pair.create(filter, executor)); 909 } 910 } 911 912 /** 913 * Removes a listener for {@link UserLifecycleEvent user lifecycle events}. 914 * 915 * @throws IllegalStateException if the listener was not added beforehand. 916 * 917 * @hide 918 */ 919 @SystemApi 920 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL}) removeListener(@onNull UserLifecycleListener listener)921 public void removeListener(@NonNull UserLifecycleListener listener) { 922 Objects.requireNonNull(listener, "listener cannot be null"); 923 924 int uid = myUid(); 925 String packageName = getContext().getPackageName(); 926 if (DBG) { 927 Slog.d(TAG, "removeListener(): uid=" + uid + ", pkg=" + packageName 928 + ", listener=" + listener); 929 } 930 synchronized (mLock) { 931 Preconditions.checkState(mListeners != null && mListeners.containsKey(listener), 932 "not called for this listener yet"); 933 mListeners.remove(listener); 934 935 // Note that there can be some rare corner cases that a listener is removed but its 936 // corresponding filter remains in the service side. This may cause slight inefficiency 937 // due to unnecessary receiver calls. It will still be functionally correct, because the 938 // removed listener will no longer be invoked. 939 if (!mListeners.isEmpty()) { 940 if (DBG) Slog.d(TAG, "removeListeners(): still " + mListeners.size() + " left"); 941 return; 942 } 943 mListeners = null; 944 945 if (mReceiver == null) { 946 Slog.wtf(TAG, "removeListener(): receiver already null"); 947 return; 948 } 949 950 EventLogHelper.writeCarUserManagerRemoveListener(uid, packageName); 951 if (DBG) { 952 Slog.d(TAG, "Removing lifecycle receiver for uid=" + uid + " and package " 953 + packageName); 954 } 955 try { 956 mService.resetLifecycleListenerForApp(mReceiver); 957 mReceiver = null; 958 } catch (RemoteException e) { 959 handleRemoteExceptionFromCarService(e); 960 } 961 } 962 } 963 964 /** 965 * Check if user hal supports user association. 966 * 967 * @hide 968 */ isUserHalUserAssociationSupported()969 public boolean isUserHalUserAssociationSupported() { 970 try { 971 return mService.isUserHalUserAssociationSupported(); 972 } catch (RemoteException | RuntimeException e) { 973 return handleExceptionFromCarService(e, false); 974 } 975 } 976 977 /** 978 * Gets the user authentication types associated with this manager's user. 979 * 980 * @hide 981 */ 982 @NonNull 983 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 984 android.Manifest.permission.CREATE_USERS}) getUserIdentificationAssociation( @serIdentificationAssociationType int... types)985 public UserIdentificationAssociationResponse getUserIdentificationAssociation( 986 @UserIdentificationAssociationType int... types) { 987 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 988 EventLogHelper.writeCarUserManagerGetUserAuthReq(convertToObjectArray(types)); 989 try { 990 UserIdentificationAssociationResponse response = 991 mService.getUserIdentificationAssociation(types); 992 if (response != null) { 993 int[] values = response.getValues(); 994 EventLogHelper.writeCarUserManagerGetUserAuthResp(convertToObjectArray(values)); 995 } 996 return response; 997 } catch (SecurityException e) { 998 throw e; 999 } catch (RemoteException | RuntimeException e) { 1000 return handleExceptionFromCarService(e, 1001 UserIdentificationAssociationResponse.forFailure(e.getMessage())); 1002 } 1003 } 1004 1005 @Nullable convertToObjectArray(int[] input)1006 private Object[] convertToObjectArray(int[] input) { 1007 if (input == null) return null; 1008 Object[] output = new Object[input.length]; 1009 for (int i = 0; i < input.length; i++) { 1010 output[i] = input[i]; 1011 } 1012 return output; 1013 } 1014 1015 /** 1016 * Sets the user authentication types associated with this manager's user. 1017 * 1018 * @hide 1019 */ 1020 @NonNull 1021 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 1022 android.Manifest.permission.CREATE_USERS}) setUserIdentificationAssociation( @serIdentificationAssociationType int[] types, @UserIdentificationAssociationSetValue int[] values)1023 public AsyncFuture<UserIdentificationAssociationResponse> setUserIdentificationAssociation( 1024 @UserIdentificationAssociationType int[] types, 1025 @UserIdentificationAssociationSetValue int[] values) { 1026 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 1027 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value"); 1028 if (types.length != values.length) { 1029 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values (" 1030 + Arrays.toString(values) + ") should have the same length"); 1031 } 1032 // TODO(b/153900032): move this logic to a common helper 1033 Object[] loggedValues = new Integer[types.length * 2]; 1034 for (int i = 0; i < types.length; i++) { 1035 loggedValues[i * 2] = types[i]; 1036 loggedValues[i * 2 + 1 ] = values[i]; 1037 } 1038 EventLogHelper.writeCarUserManagerSetUserAuthReq(loggedValues); 1039 1040 try { 1041 AndroidFuture<UserIdentificationAssociationResponse> future = 1042 new AndroidFuture<UserIdentificationAssociationResponse>() { 1043 @Override 1044 protected void onCompleted(UserIdentificationAssociationResponse result, 1045 Throwable err) { 1046 if (result != null) { 1047 int[] rawValues = result.getValues(); 1048 // TODO(b/153900032): move this logic to a common helper 1049 if (rawValues != null) { 1050 Object[] loggedValues = new Object[rawValues.length]; 1051 for (int i = 0; i < rawValues.length; i++) { 1052 loggedValues[i] = rawValues[i]; 1053 } 1054 EventLogHelper.writeCarUserManagerSetUserAuthResp(loggedValues); 1055 } 1056 } else { 1057 Slog.w(TAG, "setUserIdentificationAssociation(" + Arrays.toString(types) 1058 + ", " + Arrays.toString(values) + ") failed: " + err); 1059 } 1060 super.onCompleted(result, err); 1061 }; 1062 }; 1063 mService.setUserIdentificationAssociation(HAL_TIMEOUT_MS, types, values, future); 1064 return new AndroidAsyncFuture<>(future); 1065 } catch (SecurityException e) { 1066 throw e; 1067 } catch (RemoteException | RuntimeException e) { 1068 AndroidFuture<UserIdentificationAssociationResponse> future = new AndroidFuture<>(); 1069 future.complete(UserIdentificationAssociationResponse.forFailure()); 1070 return handleExceptionFromCarService(e, new AndroidAsyncFuture<>(future)); 1071 } 1072 } 1073 1074 /** 1075 * Sets a callback to be notified before user switch. It should only be used by Car System UI. 1076 * 1077 * @hide 1078 * @deprecated use {@link #setUserSwitchUiCallback(Executor, UserHandleSwitchUiCallback)} 1079 * instead. 1080 */ 1081 @Deprecated 1082 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) setUserSwitchUiCallback(@onNull UserSwitchUiCallback callback)1083 public void setUserSwitchUiCallback(@NonNull UserSwitchUiCallback callback) { 1084 Preconditions.checkArgument(callback != null, "Null callback"); 1085 UserHandleSwitchUiCallback userHandleSwitchUiCallback = (userHandle) -> { 1086 callback.showUserSwitchDialog(userHandle.getIdentifier()); 1087 }; 1088 setUserSwitchUiCallback(Runnable::run, userHandleSwitchUiCallback); 1089 } 1090 1091 /** 1092 * Sets a callback to be notified before user switch. 1093 * 1094 * <p> It should only be used by Car System UI. Setting this callback will notify the Car 1095 * System UI to show the user switching dialog. 1096 * 1097 * @hide 1098 */ 1099 @SystemApi 1100 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) setUserSwitchUiCallback(@onNull @allbackExecutor Executor executor, @NonNull UserHandleSwitchUiCallback callback)1101 public void setUserSwitchUiCallback(@NonNull @CallbackExecutor Executor executor, 1102 @NonNull UserHandleSwitchUiCallback callback) { 1103 Preconditions.checkArgument(callback != null, "Null callback"); 1104 UserSwitchUiCallbackReceiver userSwitchUiCallbackReceiver = 1105 new UserSwitchUiCallbackReceiver(callback); 1106 try { 1107 mService.setUserSwitchUiCallback(userSwitchUiCallbackReceiver); 1108 } catch (RemoteException e) { 1109 handleRemoteExceptionFromCarService(e); 1110 } 1111 } 1112 1113 // TODO(b/154958003): use mReceiver instead as now there are two binder objects 1114 /** 1115 * {@code ICarResultReceiver} used to receive user switch UI Callback. 1116 */ 1117 private final class UserSwitchUiCallbackReceiver extends ICarResultReceiver.Stub { 1118 1119 private final UserHandleSwitchUiCallback mUserHandleSwitchUiCallback; 1120 UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback)1121 UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback) { 1122 mUserHandleSwitchUiCallback = callback; 1123 } 1124 1125 @Override send(int userId, Bundle unused)1126 public void send(int userId, Bundle unused) throws RemoteException { 1127 mUserHandleSwitchUiCallback.onUserSwitchStart(UserHandle.of(userId)); 1128 } 1129 } 1130 1131 /** 1132 * {@code ICarResultReceiver} used to receive lifecycle events and dispatch to the proper 1133 * listener. 1134 */ 1135 private class LifecycleResultReceiver extends ICarResultReceiver.Stub { 1136 @Override send(int resultCode, Bundle resultData)1137 public void send(int resultCode, Bundle resultData) { 1138 if (resultData == null) { 1139 Slog.w(TAG, "Received result (" + resultCode + ") without data"); 1140 return; 1141 } 1142 int from = resultData.getInt(BUNDLE_PARAM_PREVIOUS_USER_ID, 1143 UserManagerHelper.USER_NULL); 1144 int to = resultCode; 1145 int eventType = resultData.getInt(BUNDLE_PARAM_ACTION); 1146 UserLifecycleEvent event = new UserLifecycleEvent(eventType, from, to); 1147 ArrayMap<UserLifecycleListener, Pair<UserLifecycleEventFilter, Executor>> listeners; 1148 synchronized (mLock) { 1149 if (mListeners == null) { 1150 Slog.w(TAG, "No listeners for event " + event); 1151 return; 1152 } 1153 listeners = new ArrayMap<>(mListeners); 1154 } 1155 int size = listeners.size(); 1156 EventLogHelper.writeCarUserManagerNotifyLifecycleListener(size, eventType, from, to); 1157 for (int i = 0; i < size; i++) { 1158 UserLifecycleListener listener = listeners.keyAt(i); 1159 UserLifecycleEventFilter filter = listeners.valueAt(i).first; 1160 if (filter != null && !filter.apply(event)) { 1161 if (DBG) { 1162 Slog.d(TAG, "Listener " + getLambdaName(listener) 1163 + " is skipped for the event " + event + " due to the filter " 1164 + filter); 1165 } 1166 continue; 1167 } 1168 Executor executor = listeners.valueAt(i).second; 1169 if (DBG) { 1170 Slog.d(TAG, "Calling " + getLambdaName(listener) + " for event " + event); 1171 } 1172 executor.execute(() -> listener.onEvent(event)); 1173 } 1174 mNumberReceivedEvents++; 1175 if (VERBOSE) { 1176 if (mEvents == null) { 1177 mEvents = new ArrayList<>(); 1178 } 1179 mEvents.add(event); 1180 } 1181 } 1182 } 1183 1184 /** @hide */ 1185 @Override onCarDisconnected()1186 public void onCarDisconnected() { 1187 // nothing to do 1188 } 1189 1190 private final class Dumper implements Dumpable { 1191 @Override dump(PrintWriter pw, String[] args)1192 public void dump(PrintWriter pw, String[] args) { 1193 String prefix = " "; 1194 1195 pw.printf("DBG=%b, VERBOSE=%b\n", DBG, VERBOSE); 1196 int listenersSize = 0; 1197 synchronized (mLock) { 1198 pw.printf("mReceiver: %s\n", mReceiver); 1199 if (mListeners == null) { 1200 pw.println("no listeners"); 1201 } else { 1202 listenersSize = mListeners.size(); 1203 pw.printf("%d listeners\n", listenersSize); 1204 } 1205 if (DBG) { 1206 for (int i = 0; i < listenersSize; i++) { 1207 pw.printf("%s%d: %s\n", prefix, i + 1, mListeners.keyAt(i)); 1208 } 1209 } 1210 } 1211 pw.printf("mNumberReceivedEvents: %d\n", mNumberReceivedEvents); 1212 if (VERBOSE && mEvents != null) { 1213 for (int i = 0; i < mEvents.size(); i++) { 1214 pw.printf("%s%d: %s\n", prefix, i + 1, mEvents.get(i)); 1215 } 1216 } 1217 } 1218 1219 @Override getDumpableName()1220 public String getDumpableName() { 1221 return CarUserManager.class.getSimpleName(); 1222 } 1223 } 1224 1225 /** 1226 * @hide 1227 */ 1228 @SystemApi 1229 @NonNull lifecycleEventTypeToString(@serLifecycleEventType int type)1230 public static String lifecycleEventTypeToString(@UserLifecycleEventType int type) { 1231 switch (type) { 1232 case USER_LIFECYCLE_EVENT_TYPE_STARTING: 1233 return "STARTING"; 1234 case USER_LIFECYCLE_EVENT_TYPE_SWITCHING: 1235 return "SWITCHING"; 1236 case USER_LIFECYCLE_EVENT_TYPE_UNLOCKING: 1237 return "UNLOCKING"; 1238 case USER_LIFECYCLE_EVENT_TYPE_UNLOCKED: 1239 return "UNLOCKED"; 1240 case USER_LIFECYCLE_EVENT_TYPE_STOPPING: 1241 return "STOPPING"; 1242 case USER_LIFECYCLE_EVENT_TYPE_STOPPED: 1243 return "STOPPED"; 1244 case USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED: 1245 return "POST_UNLOCKED"; 1246 case USER_LIFECYCLE_EVENT_TYPE_CREATED: 1247 return "CREATED"; 1248 case USER_LIFECYCLE_EVENT_TYPE_REMOVED: 1249 return "REMOVED"; 1250 case USER_LIFECYCLE_EVENT_TYPE_VISIBLE: 1251 return "VISIBLE"; 1252 case USER_LIFECYCLE_EVENT_TYPE_INVISIBLE: 1253 return "INVISIBLE"; 1254 default: 1255 return "UNKNOWN-" + type; 1256 } 1257 } 1258 1259 /** 1260 * Checks if the given {@code userId} represents a valid user. 1261 * 1262 * <p>A "valid" user: 1263 * 1264 * <ul> 1265 * <li>Must exist in the device. 1266 * <li>Is not in the process of being deleted. 1267 * <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use 1268 * {@link UserManager#isHeadlessSystemUserMode() headless system user mode}. 1269 * </ul> 1270 * 1271 * @hide 1272 * @deprecated use {@link #isValidUser(UserHandle)} instead. 1273 */ 1274 @Deprecated 1275 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 1276 android.Manifest.permission.CREATE_USERS}) isValidUser(@serIdInt int userId)1277 public boolean isValidUser(@UserIdInt int userId) { 1278 return isValidUser(UserHandle.of(userId)); 1279 } 1280 1281 /** 1282 * Checks if the given {@code userHandle} represents a valid user. 1283 * 1284 * <p>A "valid" user: 1285 * 1286 * <ul> 1287 * <li>Must exist in the device. 1288 * <li>Is not in the process of being deleted. 1289 * <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use 1290 * {@link UserManager#isHeadlessSystemUserMode() headless system user mode}. 1291 * </ul> 1292 * 1293 */ 1294 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 1295 android.Manifest.permission.CREATE_USERS}) 1296 @SuppressWarnings("UserHandle") isValidUser(@onNull UserHandle userHandle)1297 public boolean isValidUser(@NonNull UserHandle userHandle) { 1298 List<UserHandle> allUsers = mUserManager.getUserHandles(/* excludeDying=*/ true); 1299 for (int i = 0; i < allUsers.size(); i++) { 1300 UserHandle user = allUsers.get(i); 1301 if (user.equals(userHandle) && (!userHandle.equals(UserHandle.SYSTEM) 1302 || !mIsHeadlessSystemUserMode)) { 1303 return true; 1304 } 1305 } 1306 return false; 1307 } 1308 1309 /** 1310 * Defines a lifecycle event for an Android user. 1311 * 1312 * @hide 1313 */ 1314 @SystemApi 1315 public static final class UserLifecycleEvent { 1316 private final @UserLifecycleEventType int mEventType; 1317 private final @UserIdInt int mUserId; 1318 private final @UserIdInt int mPreviousUserId; 1319 1320 /** @hide */ UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int from, @UserIdInt int to)1321 public UserLifecycleEvent(@UserLifecycleEventType int eventType, 1322 @UserIdInt int from, @UserIdInt int to) { 1323 mEventType = eventType; 1324 mPreviousUserId = from; 1325 mUserId = to; 1326 } 1327 1328 /** @hide */ UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int to)1329 public UserLifecycleEvent(@UserLifecycleEventType int eventType, @UserIdInt int to) { 1330 this(eventType, UserManagerHelper.USER_NULL, to); 1331 } 1332 1333 /** 1334 * Gets the event type. 1335 * 1336 * @return either {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STARTING}, 1337 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}, 1338 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKING}, 1339 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKED}, 1340 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPING} or 1341 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPED} for all apps; 1342 * for apps {@link CarPackageManager#getTargetCarVersion() targeting car version} 1343 * {@link CarVersion.VERSION_CODES#TIRAMISU_1} or higher, it could be new types 1344 * added on later releases, such as 1345 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_CREATED}, 1346 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_REMOVED} and possibly others. 1347 * 1348 */ 1349 @UserLifecycleEventType getEventType()1350 public int getEventType() { 1351 return mEventType; 1352 } 1353 1354 /** 1355 * Gets the id of the user whose event is being reported. 1356 * 1357 * @hide 1358 */ 1359 @UserIdInt getUserId()1360 public int getUserId() { 1361 return mUserId; 1362 } 1363 1364 /** 1365 * Gets the handle of the user whose event is being reported. 1366 */ 1367 @NonNull getUserHandle()1368 public UserHandle getUserHandle() { 1369 return UserHandle.of(mUserId); 1370 } 1371 1372 /** 1373 * Gets the id of the user being switched from. 1374 * 1375 * <p>This method returns {@link UserHandle#USER_NULL} for all event types but 1376 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}. 1377 * 1378 * @hide 1379 */ 1380 @UserIdInt getPreviousUserId()1381 public int getPreviousUserId() { 1382 return mPreviousUserId; 1383 } 1384 1385 /** 1386 * Gets the handle of the user being switched from. 1387 * 1388 * <p>This method returns {@code null} for all event types but 1389 * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}. 1390 */ 1391 @Nullable getPreviousUserHandle()1392 public UserHandle getPreviousUserHandle() { 1393 return mPreviousUserId == UserManagerHelper.USER_NULL ? null 1394 : UserHandle.of(mPreviousUserId); 1395 } 1396 1397 @Override toString()1398 public String toString() { 1399 StringBuilder builder = new StringBuilder("Event[type=") 1400 .append(lifecycleEventTypeToString(mEventType)); 1401 if (mPreviousUserId != UserManagerHelper.USER_NULL) { 1402 builder 1403 .append(",from=").append(mPreviousUserId) 1404 .append(",to=").append(mUserId); 1405 } else { 1406 builder.append(",user=").append(mUserId); 1407 } 1408 1409 return builder.append(']').toString(); 1410 } 1411 1412 @Override equals(@ullable Object o)1413 public boolean equals(@Nullable Object o) { 1414 if (this == o) return true; 1415 if (o == null || getClass() != o.getClass()) return false; 1416 1417 UserLifecycleEvent that = (UserLifecycleEvent) o; 1418 return mEventType == that.mEventType && mUserId == that.mUserId 1419 && mPreviousUserId == that.mPreviousUserId; 1420 } 1421 1422 @Override hashCode()1423 public int hashCode() { 1424 int hash = 23; 1425 hash = 17 * hash + mEventType; 1426 hash = 17 * hash + mUserId; 1427 hash = 17 * hash + mPreviousUserId; 1428 1429 return hash; 1430 } 1431 } 1432 1433 /** 1434 * Listener for Android User lifecycle events. 1435 * 1436 * <p>Must be registered using {@link CarUserManager#addListener(UserLifecycleListener)} and 1437 * unregistered through {@link CarUserManager#removeListener(UserLifecycleListener)}. 1438 * 1439 * @hide 1440 */ 1441 @SystemApi 1442 public interface UserLifecycleListener { 1443 1444 /** 1445 * Called to notify the given {@code event}. 1446 */ onEvent(@onNull UserLifecycleEvent event)1447 void onEvent(@NonNull UserLifecycleEvent event); 1448 } 1449 1450 /** 1451 * Callback for notifying user switch before switch started. 1452 * 1453 * <p> It should only be used by Car System UI. The purpose of this callback is to notify the 1454 * Car System UI to display the user switch UI. 1455 * 1456 * @hide 1457 * @deprecated use {@link #UserHandleSwitchUiCallback} instead. 1458 */ 1459 @Deprecated 1460 public interface UserSwitchUiCallback { 1461 1462 /** 1463 * Called to notify that user switch dialog should be shown now. 1464 */ showUserSwitchDialog(@serIdInt int userId)1465 void showUserSwitchDialog(@UserIdInt int userId); 1466 } 1467 1468 /** 1469 * Callback for notifying user switch before switch started. 1470 * 1471 * @hide 1472 */ 1473 @SystemApi 1474 public interface UserHandleSwitchUiCallback { 1475 1476 /** 1477 * Called before the user switch starts. 1478 * 1479 * <p> This is typically used to show the user dialog. 1480 */ 1481 @SuppressWarnings("UserHandleName") onUserSwitchStart(@onNull UserHandle userHandle)1482 void onUserSwitchStart(@NonNull UserHandle userHandle); 1483 } 1484 } 1485