1 /* 2 * Copyright (C) 2018 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 com.android.car.user; 18 19 import static android.Manifest.permission.CREATE_USERS; 20 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 21 import static android.Manifest.permission.MANAGE_USERS; 22 import static android.car.builtin.os.UserManagerHelper.USER_NULL; 23 import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP; 24 25 import static com.android.car.CarServiceUtils.getHandlerThread; 26 import static com.android.car.CarServiceUtils.isMultipleUsersOnMultipleDisplaysSupported; 27 import static com.android.car.CarServiceUtils.isVisibleBackgroundUsersOnDefaultDisplaySupported; 28 import static com.android.car.CarServiceUtils.startHomeForUserAndDisplay; 29 import static com.android.car.CarServiceUtils.startSystemUiForUser; 30 import static com.android.car.CarServiceUtils.stopSystemUiForUser; 31 import static com.android.car.CarServiceUtils.toIntArray; 32 import static com.android.car.PermissionHelper.checkHasAtLeastOnePermissionGranted; 33 import static com.android.car.PermissionHelper.checkHasDumpPermissionGranted; 34 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO; 35 import static com.android.car.internal.util.VersionUtils.isPlatformVersionAtLeastU; 36 37 import android.annotation.NonNull; 38 import android.annotation.Nullable; 39 import android.annotation.UserIdInt; 40 import android.app.ActivityManager; 41 import android.app.admin.DevicePolicyManager; 42 import android.car.Car; 43 import android.car.CarOccupantZoneManager; 44 import android.car.CarOccupantZoneManager.OccupantZoneInfo; 45 import android.car.CarVersion; 46 import android.car.ICarOccupantZoneCallback; 47 import android.car.ICarResultReceiver; 48 import android.car.ICarUserService; 49 import android.car.PlatformVersion; 50 import android.car.VehicleAreaSeat; 51 import android.car.builtin.app.ActivityManagerHelper; 52 import android.car.builtin.content.pm.PackageManagerHelper; 53 import android.car.builtin.os.TraceHelper; 54 import android.car.builtin.os.UserManagerHelper; 55 import android.car.builtin.util.EventLogHelper; 56 import android.car.builtin.util.Slogf; 57 import android.car.builtin.util.TimingsTraceLog; 58 import android.car.drivingstate.CarUxRestrictions; 59 import android.car.drivingstate.ICarUxRestrictionsChangeListener; 60 import android.car.settings.CarSettings; 61 import android.car.user.CarUserManager; 62 import android.car.user.CarUserManager.UserIdentificationAssociationSetValue; 63 import android.car.user.CarUserManager.UserIdentificationAssociationType; 64 import android.car.user.CarUserManager.UserLifecycleEvent; 65 import android.car.user.CarUserManager.UserLifecycleListener; 66 import android.car.user.UserCreationRequest; 67 import android.car.user.UserCreationResult; 68 import android.car.user.UserIdentificationAssociationResponse; 69 import android.car.user.UserLifecycleEventFilter; 70 import android.car.user.UserRemovalResult; 71 import android.car.user.UserStartRequest; 72 import android.car.user.UserStartResponse; 73 import android.car.user.UserStartResult; 74 import android.car.user.UserStopRequest; 75 import android.car.user.UserStopResponse; 76 import android.car.user.UserStopResult; 77 import android.car.user.UserSwitchResult; 78 import android.car.util.concurrent.AndroidFuture; 79 import android.content.Context; 80 import android.content.pm.PackageManager; 81 import android.content.pm.PackageManager.NameNotFoundException; 82 import android.content.res.Resources; 83 import android.hardware.automotive.vehicle.CreateUserRequest; 84 import android.hardware.automotive.vehicle.CreateUserStatus; 85 import android.hardware.automotive.vehicle.InitialUserInfoRequestType; 86 import android.hardware.automotive.vehicle.InitialUserInfoResponseAction; 87 import android.hardware.automotive.vehicle.RemoveUserRequest; 88 import android.hardware.automotive.vehicle.SwitchUserRequest; 89 import android.hardware.automotive.vehicle.SwitchUserStatus; 90 import android.hardware.automotive.vehicle.UserIdentificationGetRequest; 91 import android.hardware.automotive.vehicle.UserIdentificationResponse; 92 import android.hardware.automotive.vehicle.UserIdentificationSetAssociation; 93 import android.hardware.automotive.vehicle.UserIdentificationSetRequest; 94 import android.hardware.automotive.vehicle.UserInfo; 95 import android.hardware.automotive.vehicle.UsersInfo; 96 import android.location.LocationManager; 97 import android.os.Binder; 98 import android.os.Bundle; 99 import android.os.Handler; 100 import android.os.HandlerThread; 101 import android.os.IBinder; 102 import android.os.NewUserRequest; 103 import android.os.NewUserResponse; 104 import android.os.Process; 105 import android.os.RemoteException; 106 import android.os.UserHandle; 107 import android.os.UserManager; 108 import android.provider.Settings; 109 import android.text.TextUtils; 110 import android.util.ArrayMap; 111 import android.util.Log; 112 import android.util.SparseBooleanArray; 113 import android.util.SparseIntArray; 114 import android.view.Display; 115 116 import com.android.car.CarLocalServices; 117 import com.android.car.CarLog; 118 import com.android.car.CarOccupantZoneService; 119 import com.android.car.CarServiceBase; 120 import com.android.car.CarServiceHelperWrapper; 121 import com.android.car.CarUxRestrictionsManagerService; 122 import com.android.car.R; 123 import com.android.car.am.CarActivityService; 124 import com.android.car.hal.HalCallback; 125 import com.android.car.hal.UserHalHelper; 126 import com.android.car.hal.UserHalService; 127 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 128 import com.android.car.internal.ResultCallbackImpl; 129 import com.android.car.internal.common.CommonConstants.UserLifecycleEventType; 130 import com.android.car.internal.common.UserHelperLite; 131 import com.android.car.internal.os.CarSystemProperties; 132 import com.android.car.internal.util.ArrayUtils; 133 import com.android.car.internal.util.DebugUtils; 134 import com.android.car.internal.util.FunctionalUtils; 135 import com.android.car.internal.util.IndentingPrintWriter; 136 import com.android.car.pm.CarPackageManagerService; 137 import com.android.car.power.CarPowerManagementService; 138 import com.android.car.user.InitialUserSetter.InitialUserInfo; 139 import com.android.internal.annotations.GuardedBy; 140 import com.android.internal.annotations.VisibleForTesting; 141 import com.android.internal.util.Preconditions; 142 143 import java.io.PrintWriter; 144 import java.util.ArrayDeque; 145 import java.util.ArrayList; 146 import java.util.Arrays; 147 import java.util.List; 148 import java.util.Objects; 149 import java.util.Set; 150 import java.util.concurrent.CountDownLatch; 151 import java.util.concurrent.TimeUnit; 152 153 /** 154 * User service for cars. 155 */ 156 public final class CarUserService extends ICarUserService.Stub implements CarServiceBase { 157 158 /** 159 * When this is positive, create specified number of users and assign them to passenger zones. 160 * 161 * <p>If there are other users in the system, those users will be reused. This is only used 162 * for non-user build for development purpose. 163 */ 164 @VisibleForTesting 165 static final String PROP_NUMBER_AUTO_POPULATED_USERS = 166 "com.android.car.internal.debug.num_auto_populated_users"; 167 168 @VisibleForTesting 169 static final String TAG = CarLog.tagFor(CarUserService.class); 170 171 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 172 173 /** {@code int} extra used to represent a user id in a {@link ICarResultReceiver} response. */ 174 public static final String BUNDLE_USER_ID = "user.id"; 175 /** {@code int} extra used to represent user flags in a {@link ICarResultReceiver} response. */ 176 public static final String BUNDLE_USER_FLAGS = "user.flags"; 177 /** 178 * {@code String} extra used to represent a user name in a {@link ICarResultReceiver} response. 179 */ 180 public static final String BUNDLE_USER_NAME = "user.name"; 181 /** 182 * {@code int} extra used to represent the user locales in a {@link ICarResultReceiver} 183 * response. 184 */ 185 public static final String BUNDLE_USER_LOCALES = "user.locales"; 186 /** 187 * {@code int} extra used to represent the info action in a {@link ICarResultReceiver} response. 188 */ 189 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action"; 190 191 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported."; 192 193 public static final String HANDLER_THREAD_NAME = "UserService"; 194 195 // Constants below must match value of same constants defined by ActivityManager 196 public static final int USER_OP_SUCCESS = 0; 197 public static final int USER_OP_UNKNOWN_USER = -1; 198 public static final int USER_OP_IS_CURRENT = -2; 199 public static final int USER_OP_ERROR_IS_SYSTEM = -3; 200 public static final int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP = -4; 201 202 @VisibleForTesting 203 static final String ERROR_TEMPLATE_NON_ADMIN_CANNOT_CREATE_ADMIN_USERS = 204 "Non-admin user %d can only create non-admin users"; 205 206 @VisibleForTesting 207 static final String ERROR_TEMPLATE_INVALID_USER_TYPE_AND_FLAGS_COMBINATION = 208 "Invalid combination of user type(%s) and flags (%d) for caller with restrictions"; 209 210 @VisibleForTesting 211 static final String ERROR_TEMPLATE_INVALID_FLAGS_FOR_GUEST_CREATION = 212 "Invalid flags %d specified when creating a guest user %s"; 213 214 @VisibleForTesting 215 static final String ERROR_TEMPLATE_DISALLOW_ADD_USER = 216 "Cannot create user because calling user %s has the '%s' restriction"; 217 218 /** Timeout for pre-populating users. */ 219 private static final int USER_CREATION_TIMEOUT_MS = 5_000; 220 221 private static final String BG_HANDLER_THREAD_NAME = "UserService.BG"; 222 223 private final Context mContext; 224 private final ActivityManager mAm; 225 private final UserManager mUserManager; 226 private final DevicePolicyManager mDpm; 227 private final int mMaxRunningUsers; 228 private final InitialUserSetter mInitialUserSetter; 229 230 private final Object mLockUser = new Object(); 231 @GuardedBy("mLockUser") 232 private boolean mUser0Unlocked; 233 @GuardedBy("mLockUser") 234 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>(); 235 /** A queue for createUser tasks, to prevent creating multiple users concurrently. */ 236 @GuardedBy("mLockUser") 237 private final ArrayDeque<Runnable> mCreateUserQueue; 238 /** 239 * Background users that will be restarted in garage mode. This list can include the 240 * current foreground user but the current foreground user should not be restarted. 241 */ 242 @GuardedBy("mLockUser") 243 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>(); 244 /** 245 * Keep the list of background users started here. This is wholly for debugging purpose. 246 */ 247 @GuardedBy("mLockUser") 248 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>(); 249 250 /** 251 * The list of users that are starting but not visible at the time of starting excluding system 252 * user or current user. 253 * 254 * <p>Only applicable to devices that support 255 * {@link UserManager#isVisibleBackgroundUsersSupported()} background users on secondary 256 * displays. 257 * 258 * <p>Users will be added to this list if they are not visible at the time of starting. 259 * Users in this list will be removed the first time they become visible since starting. 260 */ 261 @GuardedBy("mLockUser") 262 private final ArrayList<Integer> mNotVisibleAtStartingUsers = new ArrayList<>(); 263 264 private final UserHalService mHal; 265 266 private final HandlerThread mHandlerThread = getHandlerThread(HANDLER_THREAD_NAME); 267 private final Handler mHandler; 268 269 /** This Handler is for running background tasks which can wait. */ 270 @VisibleForTesting 271 final Handler mBgHandler = new Handler(getHandlerThread(BG_HANDLER_THREAD_NAME).getLooper()); 272 273 /** 274 * Internal listeners to be notified on new user activities events. 275 * 276 * <p>This collection should be accessed and manipulated by {@code mHandlerThread} only. 277 */ 278 private final List<InternalLifecycleListener> mUserLifecycleListeners = new ArrayList<>(); 279 280 /** 281 * App listeners to be notified on new user activities events. 282 * 283 * <p>This collection should be accessed and manipulated by {@code mHandlerThread} only. 284 */ 285 private final ArrayMap<IBinder, AppLifecycleListener> mAppLifecycleListeners = 286 new ArrayMap<>(); 287 288 /** 289 * User Id for the user switch in process, if any. 290 */ 291 @GuardedBy("mLockUser") 292 private int mUserIdForUserSwitchInProcess = USER_NULL; 293 /** 294 * Request Id for the user switch in process, if any. 295 */ 296 @GuardedBy("mLockUser") 297 private int mRequestIdForUserSwitchInProcess; 298 private final int mHalTimeoutMs = CarSystemProperties.getUserHalTimeout().orElse(5_000); 299 300 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request 301 private final boolean mSwitchGuestUserBeforeSleep; 302 303 @Nullable 304 @GuardedBy("mLockUser") 305 private UserHandle mInitialUser; 306 307 private ICarResultReceiver mUserSwitchUiReceiver; 308 309 private final CarUxRestrictionsManagerService mCarUxRestrictionService; 310 311 private final CarPackageManagerService mCarPackageManagerService; 312 313 private final CarOccupantZoneService mCarOccupantZoneService; 314 315 /** 316 * Whether some operations - like user switch - are restricted by driving safety constraints. 317 */ 318 @GuardedBy("mLockUser") 319 private boolean mUxRestricted; 320 321 /** 322 * If {@code false}, garage mode operations (background users start at garage mode entry and 323 * background users stop at garage mode exit) will be skipped. Controlled using car shell 324 * command {@code adb shell set-start-bg-users-on-garage-mode [true|false]} 325 * Purpose: Garage mode testing and simulation 326 */ 327 @GuardedBy("mLockUser") 328 private boolean mStartBackgroundUsersOnGarageMode = true; 329 330 // Whether visible background users are supported on the default display, a.k.a. passenger only 331 // systems. 332 private final boolean mIsVisibleBackgroundUsersOnDefaultDisplaySupported; 333 334 private final ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener = 335 new ICarUxRestrictionsChangeListener.Stub() { 336 @Override 337 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) { 338 setUxRestrictions(restrictions); 339 } 340 }; 341 342 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */ 343 @GuardedBy("mLockUser") 344 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1); 345 346 private final UserHandleHelper mUserHandleHelper; 347 CarUserService(@onNull Context context, @NonNull UserHalService hal, @NonNull UserManager userManager, int maxRunningUsers, @NonNull CarUxRestrictionsManagerService uxRestrictionService, @NonNull CarPackageManagerService carPackageManagerService, @NonNull CarOccupantZoneService carOccupantZoneService)348 public CarUserService(@NonNull Context context, @NonNull UserHalService hal, 349 @NonNull UserManager userManager, 350 int maxRunningUsers, 351 @NonNull CarUxRestrictionsManagerService uxRestrictionService, 352 @NonNull CarPackageManagerService carPackageManagerService, 353 @NonNull CarOccupantZoneService carOccupantZoneService) { 354 this(context, hal, userManager, new UserHandleHelper(context, userManager), 355 context.getSystemService(DevicePolicyManager.class), 356 context.getSystemService(ActivityManager.class), maxRunningUsers, 357 /* initialUserSetter= */ null, uxRestrictionService, /* handler= */ null, 358 carPackageManagerService, carOccupantZoneService); 359 } 360 361 @VisibleForTesting CarUserService(@onNull Context context, @NonNull UserHalService hal, @NonNull UserManager userManager, @NonNull UserHandleHelper userHandleHelper, @NonNull DevicePolicyManager dpm, @NonNull ActivityManager am, int maxRunningUsers, @Nullable InitialUserSetter initialUserSetter, @NonNull CarUxRestrictionsManagerService uxRestrictionService, @Nullable Handler handler, @NonNull CarPackageManagerService carPackageManagerService, @NonNull CarOccupantZoneService carOccupantZoneService)362 CarUserService(@NonNull Context context, @NonNull UserHalService hal, 363 @NonNull UserManager userManager, 364 @NonNull UserHandleHelper userHandleHelper, 365 @NonNull DevicePolicyManager dpm, 366 @NonNull ActivityManager am, 367 int maxRunningUsers, 368 @Nullable InitialUserSetter initialUserSetter, 369 @NonNull CarUxRestrictionsManagerService uxRestrictionService, 370 @Nullable Handler handler, 371 @NonNull CarPackageManagerService carPackageManagerService, 372 @NonNull CarOccupantZoneService carOccupantZoneService) { 373 Slogf.d(TAG, "CarUserService(): DBG=%b, user=%s", DBG, context.getUser()); 374 mContext = context; 375 mHal = hal; 376 mAm = am; 377 mMaxRunningUsers = maxRunningUsers; 378 mUserManager = userManager; 379 mDpm = dpm; 380 mUserHandleHelper = userHandleHelper; 381 mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler; 382 mInitialUserSetter = 383 initialUserSetter == null ? new InitialUserSetter(context, this, 384 (u) -> setInitialUser(u), mUserHandleHelper) : initialUserSetter; 385 Resources resources = context.getResources(); 386 mSwitchGuestUserBeforeSleep = resources.getBoolean( 387 R.bool.config_switchGuestUserBeforeGoingSleep); 388 mCarUxRestrictionService = uxRestrictionService; 389 mCarPackageManagerService = carPackageManagerService; 390 mIsVisibleBackgroundUsersOnDefaultDisplaySupported = 391 isVisibleBackgroundUsersOnDefaultDisplaySupported(mUserManager); 392 mCreateUserQueue = new ArrayDeque<>(UserManagerHelper.getMaxRunningUsers(context)); 393 mCarOccupantZoneService = carOccupantZoneService; 394 } 395 396 /** 397 * Priority init for setting boot user. Only HAL is ready at this time. Other components have 398 * not done init yet. 399 */ priorityInit()400 public void priorityInit() { 401 // If platform is above U, then use new boot user flow and set the boot user ASAP. 402 if (isPlatformVersionAtLeastU()) { 403 mHandler.post(() -> initBootUser(getInitialUserInfoRequestType())); 404 } 405 } 406 407 @Override init()408 public void init() { 409 if (DBG) { 410 Slogf.d(TAG, "init()"); 411 } 412 413 mCarUxRestrictionService.registerUxRestrictionsChangeListener( 414 mCarUxRestrictionsChangeListener, Display.DEFAULT_DISPLAY); 415 // Currently mOccupantZoneCallback does the task to bring up UserPicker only when displays 416 // and user assignments are changed. So it's safe not to register if visible background 417 // users are disabled. But, if we'll add more functionalies in the callback, consider to 418 // move the condition into the callback. 419 if (mIsVisibleBackgroundUsersOnDefaultDisplaySupported) { 420 mCarOccupantZoneService.registerCallback(mOccupantZoneCallback); 421 } 422 CarServiceHelperWrapper.getInstance().runOnConnection(() -> 423 setUxRestrictions(mCarUxRestrictionService.getCurrentUxRestrictions())); 424 } 425 426 private final ICarOccupantZoneCallback mOccupantZoneCallback = 427 new ICarOccupantZoneCallback.Stub() { 428 @Override 429 public void onOccupantZoneConfigChanged(int flags) throws RemoteException { 430 // Listen for changes to displays and user->display assignments and launch 431 // user picker when there is no user assigned to a display. This may be a no-op 432 // for certain cases, such as a user getting assigned to a display. 433 if ((flags & (CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_DISPLAY 434 | CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER)) != 0) { 435 if (DBG) { 436 String flagString = DebugUtils.flagsToString( 437 CarOccupantZoneManager.class, "ZONE_CONFIG_CHANGE_FLAG_", 438 flags); 439 Slogf.d(TAG, "onOccupantZoneConfigChanged: zone change flag=%s", 440 flagString); 441 } 442 startUserPicker(); 443 } 444 } 445 }; 446 447 @Override release()448 public void release() { 449 if (DBG) { 450 Slogf.d(TAG, "release()"); 451 } 452 453 mCarUxRestrictionService 454 .unregisterUxRestrictionsChangeListener(mCarUxRestrictionsChangeListener); 455 456 mCarOccupantZoneService.unregisterCallback(mOccupantZoneCallback); 457 } 458 459 @Override 460 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) dump(@onNull IndentingPrintWriter writer)461 public void dump(@NonNull IndentingPrintWriter writer) { 462 checkHasDumpPermissionGranted(mContext, "dump()"); 463 464 writer.println("*CarUserService*"); 465 writer.printf("DBG=%b\n", DBG); 466 handleDumpListeners(writer); 467 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver); 468 synchronized (mLockUser) { 469 writer.println("User0Unlocked: " + mUser0Unlocked); 470 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart); 471 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere); 472 if (mFailedToCreateUserIds.size() > 0) { 473 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds); 474 } 475 writer.printf("Is UX restricted: %b\n", mUxRestricted); 476 writer.printf("Start Background Users On Garage Mode=%s\n", 477 mStartBackgroundUsersOnGarageMode); 478 writer.printf("Initial user: %s\n", mInitialUser); 479 writer.println("Users not visible at starting: " + mNotVisibleAtStartingUsers); 480 writer.println("createUser queue size: " + mCreateUserQueue.size()); 481 } 482 writer.println("SwitchGuestUserBeforeSleep: " + mSwitchGuestUserBeforeSleep); 483 484 writer.println("MaxRunningUsers: " + mMaxRunningUsers); 485 writer.printf("User HAL: supported=%b, timeout=%dms\n", isUserHalSupported(), 486 mHalTimeoutMs); 487 488 writer.println("Relevant overlayable properties"); 489 Resources res = mContext.getResources(); 490 writer.increaseIndent(); 491 writer.printf("owner_name=%s\n", UserManagerHelper.getDefaultUserName(mContext)); 492 writer.printf("default_guest_name=%s\n", res.getString(R.string.default_guest_name)); 493 writer.printf("config_multiuserMaxRunningUsers=%d\n", 494 UserManagerHelper.getMaxRunningUsers(mContext)); 495 writer.decreaseIndent(); 496 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess); 497 writer.printf("Request Id for the user switch in process=%d\n ", 498 mRequestIdForUserSwitchInProcess); 499 writer.printf("System UI package name=%s\n", 500 PackageManagerHelper.getSystemUiPackageName(mContext)); 501 502 writer.println("Relevant Global settings"); 503 writer.increaseIndent(); 504 dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_USER_ID); 505 dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID); 506 writer.decreaseIndent(); 507 508 mInitialUserSetter.dump(writer); 509 } 510 511 // TODO(b/248608281): clean up. 512 @Nullable getOccupantZoneForDisplayId(int displayId)513 private OccupantZoneInfo getOccupantZoneForDisplayId(int displayId) { 514 List<OccupantZoneInfo> occupantZoneInfos = mCarOccupantZoneService.getAllOccupantZones(); 515 for (int index = 0; index < occupantZoneInfos.size(); index++) { 516 OccupantZoneInfo occupantZoneInfo = occupantZoneInfos.get(index); 517 int[] displays = mCarOccupantZoneService.getAllDisplaysForOccupantZone( 518 occupantZoneInfo.zoneId); 519 for (int displayIndex = 0; displayIndex < displays.length; displayIndex++) { 520 if (displays[displayIndex] == displayId) { 521 return occupantZoneInfo; 522 } 523 } 524 } 525 return null; 526 } 527 dumpGlobalProperty(IndentingPrintWriter writer, String property)528 private void dumpGlobalProperty(IndentingPrintWriter writer, String property) { 529 String value = Settings.Global.getString(mContext.getContentResolver(), property); 530 writer.printf("%s=%s\n", property, value); 531 } 532 handleDumpListeners(IndentingPrintWriter writer)533 private void handleDumpListeners(IndentingPrintWriter writer) { 534 writer.increaseIndent(); 535 CountDownLatch latch = new CountDownLatch(1); 536 mHandler.post(() -> { 537 handleDumpServiceLifecycleListeners(writer); 538 handleDumpAppLifecycleListeners(writer); 539 latch.countDown(); 540 }); 541 int timeout = 5; 542 try { 543 if (!latch.await(timeout, TimeUnit.SECONDS)) { 544 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n", 545 timeout); 546 } 547 } catch (InterruptedException e) { 548 Thread.currentThread().interrupt(); 549 writer.println("Interrupted waiting for handler thread to dump app and user listeners"); 550 } 551 writer.decreaseIndent(); 552 } 553 handleDumpServiceLifecycleListeners(PrintWriter writer)554 private void handleDumpServiceLifecycleListeners(PrintWriter writer) { 555 if (mUserLifecycleListeners.isEmpty()) { 556 writer.println("No lifecycle listeners for internal services"); 557 return; 558 } 559 int size = mUserLifecycleListeners.size(); 560 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s"); 561 String indent = " "; 562 for (int i = 0; i < size; i++) { 563 InternalLifecycleListener listener = mUserLifecycleListeners.get(i); 564 writer.printf("%slistener=%s, filter=%s\n", indent, 565 FunctionalUtils.getLambdaName(listener.listener), listener.filter); 566 } 567 } 568 handleDumpAppLifecycleListeners(IndentingPrintWriter writer)569 private void handleDumpAppLifecycleListeners(IndentingPrintWriter writer) { 570 int size = mAppLifecycleListeners.size(); 571 if (size == 0) { 572 writer.println("No lifecycle listeners for apps"); 573 return; 574 } 575 writer.printf("%d lifecycle listener%s for apps\n", size, size == 1 ? "" : "s"); 576 writer.increaseIndent(); 577 for (int i = 0; i < size; i++) { 578 mAppLifecycleListeners.valueAt(i).dump(writer); 579 } 580 writer.decreaseIndent(); 581 } 582 583 @Override setLifecycleListenerForApp(String packageName, UserLifecycleEventFilter filter, ICarResultReceiver receiver)584 public void setLifecycleListenerForApp(String packageName, UserLifecycleEventFilter filter, 585 ICarResultReceiver receiver) { 586 int uid = Binder.getCallingUid(); 587 EventLogHelper.writeCarUserServiceSetLifecycleListener(uid, packageName); 588 checkInteractAcrossUsersPermission("setLifecycleListenerForApp-" + uid + "-" + packageName); 589 590 IBinder receiverBinder = receiver.asBinder(); 591 mHandler.post(() -> { 592 AppLifecycleListener listener = mAppLifecycleListeners.get(receiverBinder); 593 if (listener == null) { 594 listener = new AppLifecycleListener(uid, packageName, receiver, filter, 595 (l) -> onListenerDeath(l)); 596 Slogf.d(TAG, "Adding %s (using binder %s) with filter %s", 597 listener, receiverBinder, filter); 598 mAppLifecycleListeners.put(receiverBinder, listener); 599 } else { 600 // Same listener already exists. Only add the additional filter. 601 Slogf.d(TAG, "Adding filter %s to the listener %s (for binder %s)", filter, 602 listener, receiverBinder); 603 listener.addFilter(filter); 604 } 605 }); 606 } 607 onListenerDeath(AppLifecycleListener listener)608 private void onListenerDeath(AppLifecycleListener listener) { 609 Slogf.i(TAG, "Removing listener %s on binder death", listener); 610 mHandler.post(() -> mAppLifecycleListeners.remove(listener.receiver.asBinder())); 611 } 612 613 @Override resetLifecycleListenerForApp(ICarResultReceiver receiver)614 public void resetLifecycleListenerForApp(ICarResultReceiver receiver) { 615 int uid = Binder.getCallingUid(); 616 checkInteractAcrossUsersPermission("resetLifecycleListenerForApp-" + uid); 617 IBinder receiverBinder = receiver.asBinder(); 618 mHandler.post(() -> { 619 AppLifecycleListener listener = mAppLifecycleListeners.get(receiverBinder); 620 if (listener == null) { 621 Slogf.e(TAG, "resetLifecycleListenerForApp(uid=%d): no listener for receiver", uid); 622 return; 623 } 624 if (listener.uid != uid) { 625 Slogf.e(TAG, "resetLifecycleListenerForApp(): uid mismatch (called by %d) for " 626 + "listener %s", uid, listener); 627 } 628 EventLogHelper.writeCarUserServiceResetLifecycleListener(uid, 629 listener.packageName); 630 if (DBG) { 631 Slogf.d(TAG, "Removing %s (using binder %s)", listener, receiverBinder); 632 } 633 mAppLifecycleListeners.remove(receiverBinder); 634 635 listener.onDestroy(); 636 }); 637 } 638 639 /** 640 * Gets the initial foreground user after the device boots or resumes from suspension. 641 * 642 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL 643 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this 644 * method returns {@code null}. 645 * 646 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior 647 * (like switching to the last active user), and this method will return the result of such 648 * operation. 649 * 650 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return 651 * {@code null}. 652 * 653 * @hide 654 */ 655 @Nullable getInitialUser()656 public UserHandle getInitialUser() { 657 checkInteractAcrossUsersPermission("getInitialUser"); 658 synchronized (mLockUser) { 659 return mInitialUser; 660 } 661 } 662 663 /** 664 * Sets the initial foreground user after the device boots or resumes from suspension. 665 */ setInitialUser(@ullable UserHandle user)666 public void setInitialUser(@Nullable UserHandle user) { 667 EventLogHelper 668 .writeCarUserServiceSetInitialUser(user == null ? USER_NULL : user.getIdentifier()); 669 synchronized (mLockUser) { 670 mInitialUser = user; 671 } 672 if (user == null) { 673 // This mean InitialUserSetter failed and could not fallback, so the initial user was 674 // not switched (and most likely is SYSTEM_USER). 675 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead? 676 Slogf.wtf(TAG, "Initial user set to null"); 677 return; 678 } 679 sendInitialUserToSystemServer(user); 680 } 681 682 /** 683 * Sets the initial foreground user after car service is crashed and reconnected. 684 */ setInitialUserFromSystemServer(@ullable UserHandle user)685 public void setInitialUserFromSystemServer(@Nullable UserHandle user) { 686 if (user == null || user.getIdentifier() == USER_NULL) { 687 Slogf.e(TAG, 688 "setInitialUserFromSystemServer: Not setting initial user as user is NULL "); 689 return; 690 } 691 692 if (DBG) { 693 Slogf.d(TAG, "setInitialUserFromSystemServer: initial User: %s", user); 694 } 695 696 synchronized (mLockUser) { 697 mInitialUser = user; 698 } 699 } 700 sendInitialUserToSystemServer(UserHandle user)701 private void sendInitialUserToSystemServer(UserHandle user) { 702 CarServiceHelperWrapper.getInstance().sendInitialUser(user); 703 } 704 initResumeReplaceGuest()705 private void initResumeReplaceGuest() { 706 int currentUserId = ActivityManager.getCurrentUser(); 707 UserHandle currentUser = mUserHandleHelper.getExistingUserHandle(currentUserId); 708 709 if (currentUser == null) { 710 Slogf.wtf(TAG, "Current user (%d) doesn't exist", currentUserId); 711 } 712 713 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest 714 715 InitialUserInfo info = 716 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build(); 717 718 mInitialUserSetter.set(info); 719 } 720 721 /** 722 * Calls to switch user at the power suspend. 723 * 724 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService} 725 * 726 */ onSuspend()727 public void onSuspend() { 728 if (DBG) { 729 Slogf.d(TAG, "onSuspend called."); 730 } 731 732 if (mSwitchGuestUserBeforeSleep) { 733 initResumeReplaceGuest(); 734 } 735 } 736 737 /** 738 * Calls to switch user at the power resume. 739 * 740 * <p> 741 * <b>Note:</b> Should be used only by {@link CarPowerManagementService} 742 * 743 */ onResume()744 public void onResume() { 745 if (DBG) { 746 Slogf.d(TAG, "onResume called."); 747 } 748 749 mHandler.post(() -> initBootUser(InitialUserInfoRequestType.RESUME)); 750 } 751 752 /** 753 * Calls to start user at the android startup. 754 */ initBootUser()755 public void initBootUser() { 756 // This check is to make sure that initBootUser is called only once during boot. 757 // For U and above, different boot user flow is used and initBootUser is called in 758 // priorityInit 759 if (!isPlatformVersionAtLeastU()) { 760 mHandler.post(() -> initBootUser(getInitialUserInfoRequestType())); 761 } 762 } 763 initBootUser(int requestType)764 private void initBootUser(int requestType) { 765 boolean replaceGuest = 766 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep; 767 checkManageUsersPermission("startInitialUser"); 768 769 // TODO(b/266473227): Fix isUserHalSupported() for Multi User No driver. 770 if (!isUserHalSupported() || mIsVisibleBackgroundUsersOnDefaultDisplaySupported) { 771 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest, 772 /* supportsOverrideUserIdProperty= */ true, requestType); 773 EventLogHelper.writeCarUserServiceInitialUserInfoReqComplete(requestType); 774 return; 775 } 776 777 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 778 EventLogHelper.writeCarUserServiceInitialUserInfoReq(requestType, 779 mHalTimeoutMs, usersInfo.currentUser.userId, usersInfo.currentUser.flags, 780 usersInfo.numberUsers); 781 782 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> { 783 if (resp != null) { 784 EventLogHelper.writeCarUserServiceInitialUserInfoResp( 785 status, resp.action, resp.userToSwitchOrCreate.userId, 786 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales); 787 788 String userLocales = resp.userLocales; 789 InitialUserInfo info; 790 switch(resp.action) { 791 case InitialUserInfoResponseAction.SWITCH: 792 int userId = resp.userToSwitchOrCreate.userId; 793 if (userId <= 0) { 794 Slogf.w(TAG, "invalid (or missing) user id sent by HAL: %d", userId); 795 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest, 796 /* supportsOverrideUserIdProperty= */ false, requestType); 797 break; 798 } 799 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH) 800 .setRequestType(requestType) 801 .setUserLocales(userLocales) 802 .setSwitchUserId(userId) 803 .setReplaceGuest(replaceGuest) 804 .build(); 805 mInitialUserSetter.set(info); 806 break; 807 808 case InitialUserInfoResponseAction.CREATE: 809 int halFlags = resp.userToSwitchOrCreate.flags; 810 String userName = resp.userNameToCreate; 811 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE) 812 .setRequestType(requestType) 813 .setUserLocales(userLocales) 814 .setNewUserName(userName) 815 .setNewUserFlags(halFlags) 816 .build(); 817 mInitialUserSetter.set(info); 818 break; 819 820 case InitialUserInfoResponseAction.DEFAULT: 821 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest, 822 /* supportsOverrideUserIdProperty= */ false, requestType); 823 break; 824 default: 825 Slogf.w(TAG, "invalid response action on %s", resp); 826 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest, 827 /* supportsOverrideUserIdProperty= */ false, requestType); 828 break; 829 830 } 831 } else { 832 EventLogHelper.writeCarUserServiceInitialUserInfoResp(status, /* action= */ 0, 833 /* userId= */ 0, /* flags= */ 0, 834 /* safeName= */ "", /* userLocales= */ ""); 835 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest, 836 /* supportsOverrideUserIdProperty= */ false, requestType); 837 } 838 EventLogHelper.writeCarUserServiceInitialUserInfoReqComplete(requestType); 839 }); 840 } 841 fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest, boolean supportsOverrideUserIdProperty, int requestType)842 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest, 843 boolean supportsOverrideUserIdProperty, int requestType) { 844 InitialUserInfo info = new InitialUserSetter.Builder( 845 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR) 846 .setRequestType(requestType) 847 .setUserLocales(userLocales) 848 .setReplaceGuest(replaceGuest) 849 .setSupportsOverrideUserIdProperty(supportsOverrideUserIdProperty) 850 .build(); 851 mInitialUserSetter.set(info); 852 } 853 854 @VisibleForTesting getInitialUserInfoRequestType()855 int getInitialUserInfoRequestType() { 856 if (!mInitialUserSetter.hasInitialUser()) { 857 return InitialUserInfoRequestType.FIRST_BOOT; 858 } 859 if (mContext.getPackageManager().isDeviceUpgrading()) { 860 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA; 861 } 862 return InitialUserInfoRequestType.COLD_BOOT; 863 } 864 setUxRestrictions(@ullable CarUxRestrictions restrictions)865 private void setUxRestrictions(@Nullable CarUxRestrictions restrictions) { 866 boolean restricted = restrictions != null 867 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP) 868 == UX_RESTRICTIONS_NO_SETUP; 869 if (DBG) { 870 Slogf.d(TAG, "setUxRestrictions(%s): restricted=%b", restrictions, restricted); 871 } else { 872 Slogf.i(TAG, "Setting UX restricted to %b", restricted); 873 } 874 875 synchronized (mLockUser) { 876 mUxRestricted = restricted; 877 } 878 CarServiceHelperWrapper.getInstance().setSafetyMode(!restricted); 879 } 880 isUxRestricted()881 private boolean isUxRestricted() { 882 synchronized (mLockUser) { 883 return mUxRestricted; 884 } 885 } 886 887 /** 888 * Calls the {@link UserHalService} and {@link ActivityManager} for user switch. 889 * 890 * <p> 891 * When everything works well, the workflow is: 892 * <ol> 893 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request 894 * type, current user id, target user id, and a callback. 895 * <li> HAL called back with SUCCESS. 896 * <li> {@link ActivityManager} is called for Android user switch. 897 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}. 898 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH 899 * request type, current user id, and target user id. In this case, the current and target 900 * user IDs would be same. 901 * <ol/> 902 * 903 * <p> 904 * Corner cases: 905 * <ul> 906 * <li> If target user is already the current user, no user switch is performed and receiver 907 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away. 908 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive 909 * {@code STATUS_HAL_INTERNAL_FAILURE}. 910 * <li> If HAL user switch call is successful, but android user switch call fails, 911 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and 912 * target user id, but in this case the current and target user IDs would be different. 913 * <li> If another user switch request for the same target user is received while previous 914 * request is in process, receiver would receive 915 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away. 916 * <li> If a user switch request is received while another user switch request for different 917 * target user is in process, the previous request would be abandoned and new request will be 918 * processed. No POST_SWITCH would be sent for the previous request. 919 * <ul/> 920 * 921 * @param targetUserId - target user Id 922 * @param timeoutMs - timeout for HAL to wait 923 * @param receiver - receiver for the results 924 */ 925 @Override switchUser(@serIdInt int targetUserId, int timeoutMs, @NonNull ResultCallbackImpl<UserSwitchResult> callback)926 public void switchUser(@UserIdInt int targetUserId, int timeoutMs, 927 @NonNull ResultCallbackImpl<UserSwitchResult> callback) { 928 EventLogHelper.writeCarUserServiceSwitchUserReq(targetUserId, timeoutMs); 929 checkManageOrCreateUsersPermission("switchUser"); 930 Objects.requireNonNull(callback); 931 UserHandle targetUser = mUserHandleHelper.getExistingUserHandle(targetUserId); 932 if (targetUser == null) { 933 sendUserSwitchResult(callback, /* isLogout= */ false, 934 UserSwitchResult.STATUS_INVALID_REQUEST); 935 return; 936 } 937 if (mUserManager.getUserSwitchability() != UserManager.SWITCHABILITY_STATUS_OK) { 938 sendUserSwitchResult(callback, /* isLogout= */ false, 939 UserSwitchResult.STATUS_NOT_SWITCHABLE); 940 return; 941 } 942 mHandler.post(() -> handleSwitchUser(targetUser, timeoutMs, callback, 943 /* isLogout= */ false)); 944 } 945 946 @Override logoutUser(int timeoutMs, @NonNull ResultCallbackImpl<UserSwitchResult> callback)947 public void logoutUser(int timeoutMs, @NonNull ResultCallbackImpl<UserSwitchResult> callback) { 948 checkManageOrCreateUsersPermission("logoutUser"); 949 Objects.requireNonNull(callback); 950 951 UserHandle targetUser = mDpm.getLogoutUser(); 952 int logoutUserId = targetUser == null ? UserManagerHelper.USER_NULL 953 : targetUser.getIdentifier(); 954 EventLogHelper.writeCarUserServiceLogoutUserReq(logoutUserId, timeoutMs); 955 956 if (targetUser == null) { 957 Slogf.w(TAG, "logoutUser() called when current user is not logged in"); 958 sendUserSwitchResult(callback, /* isLogout= */ true, 959 UserSwitchResult.STATUS_NOT_LOGGED_IN); 960 return; 961 } 962 963 mHandler.post(() -> handleSwitchUser(targetUser, timeoutMs, callback, 964 /* isLogout= */ true)); 965 } 966 handleSwitchUser(@onNull UserHandle targetUser, int timeoutMs, @NonNull ResultCallbackImpl<UserSwitchResult> callback, boolean isLogout)967 private void handleSwitchUser(@NonNull UserHandle targetUser, int timeoutMs, 968 @NonNull ResultCallbackImpl<UserSwitchResult> callback, boolean isLogout) { 969 int currentUser = ActivityManager.getCurrentUser(); 970 int targetUserId = targetUser.getIdentifier(); 971 if (currentUser == targetUserId) { 972 if (DBG) { 973 Slogf.d(TAG, "Current user is same as requested target user: %d", targetUserId); 974 } 975 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND; 976 sendUserSwitchResult(callback, isLogout, resultStatus); 977 return; 978 } 979 980 if (isUxRestricted()) { 981 sendUserSwitchResult(callback, isLogout, 982 UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE); 983 return; 984 } 985 986 // If User Hal is not supported, just android user switch. 987 if (!isUserHalSupported()) { 988 int result = switchOrLogoutUser(targetUser, isLogout); 989 if (result == UserManager.USER_OPERATION_SUCCESS) { 990 sendUserSwitchResult(callback, isLogout, UserSwitchResult.STATUS_SUCCESSFUL); 991 return; 992 } 993 sendUserSwitchResult(callback, isLogout, HalCallback.STATUS_INVALID, 994 UserSwitchResult.STATUS_ANDROID_FAILURE, result, /* errorMessage= */ null); 995 return; 996 } 997 998 synchronized (mLockUser) { 999 if (DBG) { 1000 Slogf.d(TAG, "handleSwitchUser(%d): currentuser=%s, isLogout=%b, " 1001 + "mUserIdForUserSwitchInProcess=%b", targetUserId, currentUser, isLogout, 1002 mUserIdForUserSwitchInProcess); 1003 } 1004 1005 // If there is another request for the same target user, return another request in 1006 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link 1007 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another 1008 // user switch request in process for different target user, but that request is now 1009 // ignored. 1010 if (mUserIdForUserSwitchInProcess == targetUserId) { 1011 Slogf.w(TAG, "switchUser(%s): another user switch request (id=%d) in process for " 1012 + "that user", targetUser, mRequestIdForUserSwitchInProcess); 1013 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO; 1014 sendUserSwitchResult(callback, isLogout, resultStatus); 1015 return; 1016 } else { 1017 if (DBG) { 1018 Slogf.d(TAG, "Changing mUserIdForUserSwitchInProcess from %d to %d", 1019 mUserIdForUserSwitchInProcess, targetUserId); 1020 } 1021 mUserIdForUserSwitchInProcess = targetUserId; 1022 mRequestIdForUserSwitchInProcess = 0; 1023 } 1024 } 1025 1026 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1027 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo); 1028 1029 if (DBG) { 1030 Slogf.d(TAG, "calling mHal.switchUser(%s)", request); 1031 } 1032 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> { 1033 if (DBG) { 1034 Slogf.d(TAG, "switch response: status=%s, resp=%s", 1035 Integer.toString(halCallbackStatus), resp); 1036 } 1037 1038 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE; 1039 Integer androidFailureStatus = null; 1040 1041 synchronized (mLockUser) { 1042 if (halCallbackStatus != HalCallback.STATUS_OK || resp == null) { 1043 Slogf.w(TAG, "invalid callback status (%s) or null response (%s)", 1044 Integer.toString(halCallbackStatus), resp); 1045 sendUserSwitchResult(callback, isLogout, resultStatus); 1046 mUserIdForUserSwitchInProcess = USER_NULL; 1047 return; 1048 } 1049 1050 if (mUserIdForUserSwitchInProcess != targetUserId) { 1051 // Another user switch request received while HAL responded. No need to 1052 // process this request further 1053 Slogf.w(TAG, "Another user switch received while HAL responsed. Request" 1054 + " abandoned for user %d. Current user in process: %d", targetUserId, 1055 mUserIdForUserSwitchInProcess); 1056 resultStatus = 1057 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST; 1058 sendUserSwitchResult(callback, isLogout, resultStatus); 1059 mUserIdForUserSwitchInProcess = USER_NULL; 1060 return; 1061 } 1062 1063 switch (resp.status) { 1064 case SwitchUserStatus.SUCCESS: 1065 int result = switchOrLogoutUser(targetUser, isLogout); 1066 if (result == UserManager.USER_OPERATION_SUCCESS) { 1067 sendUserSwitchUiCallback(targetUserId); 1068 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL; 1069 mRequestIdForUserSwitchInProcess = resp.requestId; 1070 } else { 1071 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE; 1072 if (isLogout) { 1073 // Send internal result (there's no point on sending for regular 1074 // switch as it will always be UNKNOWN_ERROR 1075 androidFailureStatus = result; 1076 } 1077 postSwitchHalResponse(resp.requestId, targetUserId); 1078 } 1079 break; 1080 case SwitchUserStatus.FAILURE: 1081 // HAL failed to switch user 1082 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE; 1083 break; 1084 default: 1085 // Shouldn't happen because UserHalService validates the status 1086 Slogf.wtf(TAG, "Received invalid user switch status from HAL: %s", resp); 1087 } 1088 1089 if (mRequestIdForUserSwitchInProcess == 0) { 1090 mUserIdForUserSwitchInProcess = USER_NULL; 1091 } 1092 } 1093 sendUserSwitchResult(callback, isLogout, halCallbackStatus, resultStatus, 1094 androidFailureStatus, resp.errorMessage); 1095 }); 1096 } 1097 switchOrLogoutUser(UserHandle targetUser, boolean isLogout)1098 private int switchOrLogoutUser(UserHandle targetUser, boolean isLogout) { 1099 if (isLogout) { 1100 int result = mDpm.logoutUser(); 1101 if (result != UserManager.USER_OPERATION_SUCCESS) { 1102 Slogf.w(TAG, "failed to logout to user %s using DPM: result=%s", targetUser, 1103 userOperationErrorToString(result)); 1104 } 1105 return result; 1106 } 1107 1108 if (!mAm.switchUser(targetUser)) { 1109 Slogf.w(TAG, "failed to switch to user %s using AM", targetUser); 1110 return UserManager.USER_OPERATION_ERROR_UNKNOWN; 1111 } 1112 1113 return UserManager.USER_OPERATION_SUCCESS; 1114 } 1115 1116 @Override removeUser(@serIdInt int userId, ResultCallbackImpl<UserRemovalResult> callback)1117 public void removeUser(@UserIdInt int userId, ResultCallbackImpl<UserRemovalResult> callback) { 1118 removeUser(userId, /* hasCallerRestrictions= */ false, callback); 1119 } 1120 1121 /** 1122 * Internal implementation of {@code removeUser()}, which is used by both 1123 * {@code ICarUserService} and {@code ICarDevicePolicyService}. 1124 * 1125 * @param userId user to be removed 1126 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can 1127 * only remove itself. 1128 * @param callback to post results 1129 */ removeUser(@serIdInt int userId, boolean hasCallerRestrictions, ResultCallbackImpl<UserRemovalResult> callback)1130 public void removeUser(@UserIdInt int userId, boolean hasCallerRestrictions, 1131 ResultCallbackImpl<UserRemovalResult> callback) { 1132 checkManageOrCreateUsersPermission("removeUser"); 1133 EventLogHelper.writeCarUserServiceRemoveUserReq(userId, 1134 hasCallerRestrictions ? 1 : 0); 1135 1136 if (hasCallerRestrictions) { 1137 // Restrictions: non-admin user can only remove itself, admins have no restrictions 1138 int callingUserId = Binder.getCallingUserHandle().getIdentifier(); 1139 if (!mUserHandleHelper.isAdminUser(UserHandle.of(callingUserId)) 1140 && userId != callingUserId) { 1141 throw new SecurityException("Non-admin user " + callingUserId 1142 + " can only remove itself"); 1143 } 1144 } 1145 mHandler.post(() -> handleRemoveUser(userId, hasCallerRestrictions, callback)); 1146 } 1147 handleRemoveUser(@serIdInt int userId, boolean hasCallerRestrictions, ResultCallbackImpl<UserRemovalResult> callback)1148 private void handleRemoveUser(@UserIdInt int userId, boolean hasCallerRestrictions, 1149 ResultCallbackImpl<UserRemovalResult> callback) { 1150 UserHandle user = mUserHandleHelper.getExistingUserHandle(userId); 1151 if (user == null) { 1152 sendUserRemovalResult(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST, callback); 1153 return; 1154 } 1155 UserInfo halUser = new UserInfo(); 1156 halUser.userId = user.getIdentifier(); 1157 halUser.flags = UserHalHelper.convertFlags(mUserHandleHelper, user); 1158 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1159 1160 // check if the user is last admin user. 1161 boolean isLastAdmin = false; 1162 if (UserHalHelper.isAdmin(halUser.flags)) { 1163 int size = usersInfo.existingUsers.length; 1164 int totalAdminUsers = 0; 1165 for (int i = 0; i < size; i++) { 1166 if (UserHalHelper.isAdmin(usersInfo.existingUsers[i].flags)) { 1167 totalAdminUsers++; 1168 } 1169 } 1170 if (totalAdminUsers == 1) { 1171 isLastAdmin = true; 1172 } 1173 } 1174 1175 // First remove user from android and then remove from HAL because HAL remove user is one 1176 // way call. 1177 // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an 1178 // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as 1179 // it's counter-intuitive that it's "allowed even when disallowed" when it 1180 // "has caller restrictions" 1181 boolean overrideDevicePolicy = hasCallerRestrictions; 1182 int result = mUserManager.removeUserWhenPossible(user, overrideDevicePolicy); 1183 if (!UserManager.isRemoveResultSuccessful(result)) { 1184 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, callback); 1185 return; 1186 } 1187 1188 if (isLastAdmin) { 1189 Slogf.w(TAG, "Last admin user successfully removed or set ephemeral. User Id: %d", 1190 userId); 1191 } 1192 1193 switch (result) { 1194 case UserManager.REMOVE_RESULT_REMOVED: 1195 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED: 1196 sendUserRemovalResult(userId, 1197 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED 1198 : UserRemovalResult.STATUS_SUCCESSFUL, callback); 1199 break; 1200 case UserManager.REMOVE_RESULT_DEFERRED: 1201 sendUserRemovalResult(userId, 1202 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL 1203 : UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL, callback); 1204 break; 1205 default: 1206 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, callback); 1207 } 1208 } 1209 1210 /** 1211 * Should be called by {@code ICarImpl} only. 1212 */ onUserRemoved(@onNull UserHandle user)1213 public void onUserRemoved(@NonNull UserHandle user) { 1214 if (DBG) { 1215 Slogf.d(TAG, "onUserRemoved: %s", user); 1216 } 1217 notifyHalUserRemoved(user); 1218 } 1219 notifyHalUserRemoved(@onNull UserHandle user)1220 private void notifyHalUserRemoved(@NonNull UserHandle user) { 1221 if (!isUserHalSupported()) return; 1222 1223 if (user == null) { 1224 Slogf.wtf(TAG, "notifyHalUserRemoved() called for null user"); 1225 return; 1226 } 1227 1228 int userId = user.getIdentifier(); 1229 1230 if (userId == USER_NULL) { 1231 Slogf.wtf(TAG, "notifyHalUserRemoved() called for USER_NULL"); 1232 return; 1233 } 1234 1235 synchronized (mLockUser) { 1236 if (mFailedToCreateUserIds.get(userId)) { 1237 if (DBG) { 1238 Slogf.d(TAG, "notifyHalUserRemoved(): skipping user %d", userId); 1239 } 1240 mFailedToCreateUserIds.delete(userId); 1241 return; 1242 } 1243 } 1244 1245 UserInfo halUser = new UserInfo(); 1246 halUser.userId = userId; 1247 halUser.flags = UserHalHelper.convertFlags(mUserHandleHelper, user); 1248 1249 RemoveUserRequest request = UserHalHelper.emptyRemoveUserRequest(); 1250 request.removedUserInfo = halUser; 1251 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1252 mHal.removeUser(request); 1253 } 1254 sendUserRemovalResult(@serIdInt int userId, @UserRemovalResult.Status int result, ResultCallbackImpl<UserRemovalResult> callback)1255 private void sendUserRemovalResult(@UserIdInt int userId, @UserRemovalResult.Status int result, 1256 ResultCallbackImpl<UserRemovalResult> callback) { 1257 EventLogHelper.writeCarUserServiceRemoveUserResp(userId, result); 1258 callback.complete(new UserRemovalResult(result)); 1259 } 1260 sendUserSwitchUiCallback(@serIdInt int targetUserId)1261 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) { 1262 if (mUserSwitchUiReceiver == null) { 1263 Slogf.w(TAG, "No User switch UI receiver."); 1264 return; 1265 } 1266 1267 EventLogHelper.writeCarUserServiceSwitchUserUiReq(targetUserId); 1268 try { 1269 mUserSwitchUiReceiver.send(targetUserId, null); 1270 } catch (RemoteException e) { 1271 Slogf.e(TAG, "Error calling user switch UI receiver.", e); 1272 } 1273 } 1274 1275 /** 1276 * Used to create the initial user, even when it's disallowed by {@code DevicePolicyManager}. 1277 */ 1278 @Nullable createUserEvenWhenDisallowed(@ullable String name, @NonNull String userType, int flags)1279 UserHandle createUserEvenWhenDisallowed(@Nullable String name, @NonNull String userType, 1280 int flags) { 1281 return CarServiceHelperWrapper.getInstance().createUserEvenWhenDisallowed(name, userType, 1282 flags); 1283 } 1284 1285 /** 1286 * Same as {@link UserManager#isUserVisible()}, but passing the user id. 1287 */ isUserVisible(@serIdInt int userId)1288 public boolean isUserVisible(@UserIdInt int userId) { 1289 if (isPlatformVersionAtLeastU()) { 1290 Set<UserHandle> visibleUsers = mUserManager.getVisibleUsers(); 1291 return visibleUsers.contains(UserHandle.of(userId)); 1292 } 1293 return false; 1294 } 1295 1296 // TODO(b/244370727): Remove once the lifecycle event callbacks provide the display id. 1297 /** 1298 * Same as {@link UserManager#getMainDisplayIdAssignedToUser()}. 1299 */ getMainDisplayAssignedToUser(int userId)1300 public int getMainDisplayAssignedToUser(int userId) { 1301 return CarServiceHelperWrapper.getInstance().getMainDisplayAssignedToUser(userId); 1302 } 1303 1304 @Override createUser(@onNull UserCreationRequest userCreationRequest, int timeoutMs, ResultCallbackImpl<UserCreationResult> callback)1305 public void createUser(@NonNull UserCreationRequest userCreationRequest, int timeoutMs, 1306 ResultCallbackImpl<UserCreationResult> callback) { 1307 String name = userCreationRequest.getName(); 1308 String userType = userCreationRequest.isGuest() ? UserManager.USER_TYPE_FULL_GUEST 1309 : UserManager.USER_TYPE_FULL_SECONDARY; 1310 int flags = 0; 1311 flags |= userCreationRequest.isAdmin() ? UserManagerHelper.FLAG_ADMIN : 0; 1312 flags |= userCreationRequest.isEphemeral() ? UserManagerHelper.FLAG_EPHEMERAL : 0; 1313 1314 createUser(name, userType, flags, timeoutMs, callback, /* hasCallerRestrictions= */ false); 1315 } 1316 1317 /** 1318 * Internal implementation of {@code createUser()}, which is used by both 1319 * {@code ICarUserService} and {@code ICarDevicePolicyService}. 1320 * 1321 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can 1322 * only create admin users 1323 */ createUser(@ullable String name, @NonNull String userType, int flags, int timeoutMs, @NonNull ResultCallbackImpl<UserCreationResult> callback, boolean hasCallerRestrictions)1324 public void createUser(@Nullable String name, @NonNull String userType, int flags, 1325 int timeoutMs, @NonNull ResultCallbackImpl<UserCreationResult> callback, 1326 boolean hasCallerRestrictions) { 1327 Objects.requireNonNull(userType, "user type cannot be null"); 1328 Objects.requireNonNull(callback, "receiver cannot be null"); 1329 checkManageOrCreateUsersPermission(flags); 1330 EventLogHelper.writeCarUserServiceCreateUserReq(UserHelperLite.safeName(name), userType, 1331 flags, timeoutMs, hasCallerRestrictions ? 1 : 0); 1332 1333 UserHandle callingUser = Binder.getCallingUserHandle(); 1334 if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_ADD_USER, callingUser)) { 1335 String internalErrorMessage = String.format(ERROR_TEMPLATE_DISALLOW_ADD_USER, 1336 callingUser, UserManager.DISALLOW_ADD_USER); 1337 Slogf.w(TAG, internalErrorMessage); 1338 sendUserCreationFailure(callback, UserCreationResult.STATUS_ANDROID_FAILURE, 1339 internalErrorMessage); 1340 return; 1341 } 1342 1343 // We use a queue to avoid concurrent user creations. Just posting the tasks to the handler 1344 // will not work here because handleCreateUser() calls UserHalService#createUser(), 1345 // which is an asynchronous call. Two consecutive createUser requests would result in 1346 // STATUS_CONCURRENT_OPERATION error from UserHalService. 1347 enqueueCreateUser(() -> handleCreateUser(name, userType, flags, timeoutMs, callback, 1348 callingUser, hasCallerRestrictions)); 1349 } 1350 enqueueCreateUser(Runnable runnable)1351 private void enqueueCreateUser(Runnable runnable) { 1352 // If the createUser queue is empty, add the task to the queue and post it to handler. 1353 // Otherwise, just add it to the queue. It will be handled once the current task finishes. 1354 synchronized (mLockUser) { 1355 if (mCreateUserQueue.isEmpty()) { 1356 // We need to push the current job to the queue and keep it in the queue until it 1357 // finishes, so that we can know the service is busy when the next job arrives. 1358 mCreateUserQueue.offer(runnable); 1359 mHandler.post(runnable); 1360 } else { 1361 mCreateUserQueue.offer(runnable); 1362 if (DBG) { 1363 Slogf.d(TAG, "createUser: Another user is currently being created." 1364 + " The request is queued for later execution."); 1365 } 1366 } 1367 } 1368 } 1369 postNextCreateUserIfAvailable()1370 private void postNextCreateUserIfAvailable() { 1371 synchronized (mLockUser) { 1372 // Remove the current job from the queue. 1373 mCreateUserQueue.poll(); 1374 1375 // Post the next job if there is any left in the queue. 1376 Runnable runnable = mCreateUserQueue.peek(); 1377 if (runnable != null) { 1378 mHandler.post(runnable); 1379 if (DBG) { 1380 Slogf.d(TAG, "createUser: A previously queued request is now being executed."); 1381 } 1382 } 1383 } 1384 } 1385 handleCreateUser(@ullable String name, @NonNull String userType, int flags, int timeoutMs, @NonNull ResultCallbackImpl<UserCreationResult> callback, @NonNull UserHandle callingUser, boolean hasCallerRestrictions)1386 private void handleCreateUser(@Nullable String name, @NonNull String userType, 1387 int flags, int timeoutMs, @NonNull ResultCallbackImpl<UserCreationResult> callback, 1388 @NonNull UserHandle callingUser, boolean hasCallerRestrictions) { 1389 if (userType.equals(UserManager.USER_TYPE_FULL_GUEST) && flags != 0) { 1390 // Non-zero flags are not allowed when creating a guest user. 1391 String internalErroMessage = String 1392 .format(ERROR_TEMPLATE_INVALID_FLAGS_FOR_GUEST_CREATION, flags, name); 1393 Slogf.e(TAG, internalErroMessage); 1394 sendUserCreationFailure(callback, UserCreationResult.STATUS_INVALID_REQUEST, 1395 internalErroMessage); 1396 return; 1397 } 1398 if (hasCallerRestrictions) { 1399 // Restrictions: 1400 // - type/flag can only be normal user, admin, or guest 1401 // - non-admin user can only create non-admin users 1402 1403 boolean validCombination; 1404 switch (userType) { 1405 case UserManager.USER_TYPE_FULL_SECONDARY: 1406 validCombination = flags == 0 1407 || (flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN; 1408 break; 1409 case UserManager.USER_TYPE_FULL_GUEST: 1410 validCombination = true; 1411 break; 1412 default: 1413 validCombination = false; 1414 } 1415 if (!validCombination) { 1416 String internalErrorMessage = String.format( 1417 ERROR_TEMPLATE_INVALID_USER_TYPE_AND_FLAGS_COMBINATION, userType, flags); 1418 1419 Slogf.d(TAG, internalErrorMessage); 1420 sendUserCreationFailure(callback, UserCreationResult.STATUS_INVALID_REQUEST, 1421 internalErrorMessage); 1422 return; 1423 } 1424 1425 if (!mUserHandleHelper.isAdminUser(callingUser) 1426 && (flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) { 1427 String internalErrorMessage = String 1428 .format(ERROR_TEMPLATE_NON_ADMIN_CANNOT_CREATE_ADMIN_USERS, 1429 callingUser.getIdentifier()); 1430 Slogf.d(TAG, internalErrorMessage); 1431 sendUserCreationFailure(callback, UserCreationResult.STATUS_INVALID_REQUEST, 1432 internalErrorMessage); 1433 return; 1434 } 1435 } 1436 1437 NewUserRequest newUserRequest; 1438 try { 1439 newUserRequest = getCreateUserRequest(name, userType, flags); 1440 } catch (Exception e) { 1441 Slogf.e(TAG, e, "Error creating new user request. name: %s UserType: %s and flags: %s", 1442 name, userType, flags); 1443 sendUserCreationResult(callback, UserCreationResult.STATUS_ANDROID_FAILURE, 1444 UserManager.USER_OPERATION_ERROR_UNKNOWN, /* user= */ null, 1445 /* errorMessage= */ null, e.toString()); 1446 return; 1447 } 1448 1449 UserHandle newUser; 1450 try { 1451 NewUserResponse newUserResponse = mUserManager.createUser(newUserRequest); 1452 1453 if (!newUserResponse.isSuccessful()) { 1454 if (DBG) { 1455 Slogf.d(TAG, "um.createUser() returned null for user of type %s and flags %d", 1456 userType, flags); 1457 } 1458 sendUserCreationResult(callback, UserCreationResult.STATUS_ANDROID_FAILURE, 1459 newUserResponse.getOperationResult(), /* user= */ null, 1460 /* errorMessage= */ null, /* internalErrorMessage= */ null); 1461 return; 1462 } 1463 1464 newUser = newUserResponse.getUser(); 1465 1466 if (DBG) { 1467 Slogf.d(TAG, "Created user: %s", newUser); 1468 } 1469 EventLogHelper.writeCarUserServiceCreateUserUserCreated(newUser.getIdentifier(), name, 1470 userType, flags); 1471 } catch (RuntimeException e) { 1472 Slogf.e(TAG, e, "Error creating user of type %s and flags %d", userType, flags); 1473 sendUserCreationResult(callback, UserCreationResult.STATUS_ANDROID_FAILURE, 1474 UserManager.USER_OPERATION_ERROR_UNKNOWN, /* user= */ null, 1475 /* errorMessage= */ null, e.toString()); 1476 return; 1477 } 1478 1479 if (!isUserHalSupported()) { 1480 sendUserCreationResult(callback, UserCreationResult.STATUS_SUCCESSFUL, 1481 /* androidFailureStatus= */ null , newUser, /* errorMessage= */ null, 1482 /* internalErrorMessage= */ null); 1483 return; 1484 } 1485 1486 CreateUserRequest request = UserHalHelper.emptyCreateUserRequest(); 1487 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1488 if (!TextUtils.isEmpty(name)) { 1489 request.newUserName = name; 1490 } 1491 request.newUserInfo.userId = newUser.getIdentifier(); 1492 request.newUserInfo.flags = UserHalHelper.convertFlags(mUserHandleHelper, newUser); 1493 if (DBG) { 1494 Slogf.d(TAG, "Create user request: %s", request); 1495 } 1496 1497 try { 1498 mHal.createUser(request, timeoutMs, (status, resp) -> { 1499 String errorMessage = resp != null ? resp.errorMessage : null; 1500 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE; 1501 if (DBG) { 1502 Slogf.d(TAG, "createUserResponse: status=%s, resp=%s", 1503 UserHalHelper.halCallbackStatusToString(status), resp); 1504 } 1505 UserHandle user = null; // user returned in the result 1506 if (status != HalCallback.STATUS_OK || resp == null) { 1507 Slogf.w(TAG, "invalid callback status (%s) or null response (%s)", 1508 UserHalHelper.halCallbackStatusToString(status), resp); 1509 EventLogHelper.writeCarUserServiceCreateUserResp(status, resultStatus, 1510 errorMessage); 1511 removeCreatedUser(newUser, "HAL call failed with " 1512 + UserHalHelper.halCallbackStatusToString(status)); 1513 sendUserCreationResult(callback, resultStatus, /* androidFailureStatus= */ null, 1514 user, errorMessage, /* internalErrorMessage= */ null); 1515 return; 1516 } 1517 1518 switch (resp.status) { 1519 case CreateUserStatus.SUCCESS: 1520 resultStatus = UserCreationResult.STATUS_SUCCESSFUL; 1521 user = newUser; 1522 break; 1523 case CreateUserStatus.FAILURE: 1524 // HAL failed to switch user 1525 resultStatus = UserCreationResult.STATUS_HAL_FAILURE; 1526 break; 1527 default: 1528 // Shouldn't happen because UserHalService validates the status 1529 Slogf.wtf(TAG, "Received invalid user switch status from HAL: %s", resp); 1530 } 1531 EventLogHelper.writeCarUserServiceCreateUserResp(status, resultStatus, 1532 errorMessage); 1533 if (user == null) { 1534 removeCreatedUser(newUser, "HAL returned " 1535 + UserCreationResult.statusToString(resultStatus)); 1536 } 1537 sendUserCreationResult(callback, resultStatus, /* androidFailureStatus= */ null, 1538 user, errorMessage, /* internalErrorMessage= */ null); 1539 }); 1540 } catch (Exception e) { 1541 Slogf.w(TAG, e, "mHal.createUser(%s) failed", request); 1542 removeCreatedUser(newUser, "mHal.createUser() failed"); 1543 sendUserCreationFailure(callback, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE, 1544 e.toString()); 1545 } 1546 } 1547 getCreateUserRequest(String name, String userType, int flags)1548 private NewUserRequest getCreateUserRequest(String name, String userType, int flags) { 1549 NewUserRequest.Builder builder = new NewUserRequest.Builder().setName(name) 1550 .setUserType(userType); 1551 if ((flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) { 1552 builder.setAdmin(); 1553 } 1554 1555 if ((flags & UserManagerHelper.FLAG_EPHEMERAL) == UserManagerHelper.FLAG_EPHEMERAL) { 1556 builder.setEphemeral(); 1557 } 1558 1559 return builder.build(); 1560 } 1561 removeCreatedUser(@onNull UserHandle user, @NonNull String reason)1562 private void removeCreatedUser(@NonNull UserHandle user, @NonNull String reason) { 1563 Slogf.i(TAG, "removing user %s reason: %s", user, reason); 1564 1565 int userId = user.getIdentifier(); 1566 EventLogHelper.writeCarUserServiceCreateUserUserRemoved(userId, reason); 1567 1568 synchronized (mLockUser) { 1569 mFailedToCreateUserIds.put(userId, true); 1570 } 1571 1572 try { 1573 if (!mUserManager.removeUser(user)) { 1574 Slogf.w(TAG, "Failed to remove user %s", user); 1575 } 1576 } catch (Exception e) { 1577 Slogf.e(TAG, e, "Failed to remove user %s", user); 1578 } 1579 } 1580 1581 @Override getUserIdentificationAssociation( @serIdentificationAssociationType int[] types)1582 public UserIdentificationAssociationResponse getUserIdentificationAssociation( 1583 @UserIdentificationAssociationType int[] types) { 1584 if (!isUserHalUserAssociationSupported()) { 1585 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED); 1586 } 1587 1588 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 1589 checkManageOrCreateUsersPermission("getUserIdentificationAssociation"); 1590 1591 int uid = getCallingUid(); 1592 int userId = getCallingUserHandle().getIdentifier(); 1593 EventLogHelper.writeCarUserServiceGetUserAuthReq(uid, userId, types.length); 1594 1595 UserIdentificationGetRequest request = UserHalHelper.emptyUserIdentificationGetRequest(); 1596 request.userInfo.userId = userId; 1597 request.userInfo.flags = getHalUserInfoFlags(userId); 1598 1599 request.numberAssociationTypes = types.length; 1600 ArrayList<Integer> associationTypes = new ArrayList<>(types.length); 1601 for (int i = 0; i < types.length; i++) { 1602 associationTypes.add(types[i]); 1603 } 1604 request.associationTypes = toIntArray(associationTypes); 1605 1606 UserIdentificationResponse halResponse = mHal.getUserAssociation(request); 1607 if (halResponse == null) { 1608 Slogf.w(TAG, "getUserIdentificationAssociation(): HAL returned null for %s", 1609 Arrays.toString(types)); 1610 return UserIdentificationAssociationResponse.forFailure(); 1611 } 1612 1613 int[] values = new int[halResponse.associations.length]; 1614 for (int i = 0; i < values.length; i++) { 1615 values[i] = halResponse.associations[i].value; 1616 } 1617 EventLogHelper.writeCarUserServiceGetUserAuthResp(values.length); 1618 1619 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage); 1620 } 1621 1622 @Override setUserIdentificationAssociation(int timeoutMs, @UserIdentificationAssociationType int[] types, @UserIdentificationAssociationSetValue int[] values, AndroidFuture<UserIdentificationAssociationResponse> result)1623 public void setUserIdentificationAssociation(int timeoutMs, 1624 @UserIdentificationAssociationType int[] types, 1625 @UserIdentificationAssociationSetValue int[] values, 1626 AndroidFuture<UserIdentificationAssociationResponse> result) { 1627 if (!isUserHalUserAssociationSupported()) { 1628 result.complete( 1629 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED)); 1630 return; 1631 } 1632 1633 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 1634 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value"); 1635 if (types.length != values.length) { 1636 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values (" 1637 + Arrays.toString(values) + ") should have the same length"); 1638 } 1639 checkManageOrCreateUsersPermission("setUserIdentificationAssociation"); 1640 1641 int uid = getCallingUid(); 1642 int userId = getCallingUserHandle().getIdentifier(); 1643 EventLogHelper.writeCarUserServiceSetUserAuthReq(uid, userId, types.length); 1644 1645 UserIdentificationSetRequest request = UserHalHelper.emptyUserIdentificationSetRequest(); 1646 request.userInfo.userId = userId; 1647 request.userInfo.flags = getHalUserInfoFlags(userId); 1648 1649 request.numberAssociations = types.length; 1650 ArrayList<UserIdentificationSetAssociation> associations = new ArrayList<>(); 1651 for (int i = 0; i < types.length; i++) { 1652 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation(); 1653 association.type = types[i]; 1654 association.value = values[i]; 1655 associations.add(association); 1656 } 1657 request.associations = 1658 associations.toArray(new UserIdentificationSetAssociation[associations.size()]); 1659 1660 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> { 1661 if (status != HalCallback.STATUS_OK || resp == null) { 1662 Slogf.w(TAG, "setUserIdentificationAssociation(): invalid callback status (%s) for " 1663 + "response %s", UserHalHelper.halCallbackStatusToString(status), resp); 1664 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) { 1665 EventLogHelper.writeCarUserServiceSetUserAuthResp(0, /* errorMessage= */ ""); 1666 result.complete(UserIdentificationAssociationResponse.forFailure()); 1667 return; 1668 } 1669 EventLogHelper.writeCarUserServiceSetUserAuthResp(0, resp.errorMessage); 1670 result.complete( 1671 UserIdentificationAssociationResponse.forFailure(resp.errorMessage)); 1672 return; 1673 } 1674 int respSize = resp.associations.length; 1675 EventLogHelper.writeCarUserServiceSetUserAuthResp(respSize, resp.errorMessage); 1676 1677 int[] responseTypes = new int[respSize]; 1678 for (int i = 0; i < respSize; i++) { 1679 responseTypes[i] = resp.associations[i].value; 1680 } 1681 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse 1682 .forSuccess(responseTypes, resp.errorMessage); 1683 if (DBG) { 1684 Slogf.d(TAG, "setUserIdentificationAssociation(): resp=%s, converted=%s", resp, 1685 response); 1686 } 1687 result.complete(response); 1688 }); 1689 } 1690 1691 /** 1692 * Gets the User HAL flags for the given user. 1693 * 1694 * @throws IllegalArgumentException if the user does not exist. 1695 */ getHalUserInfoFlags(@serIdInt int userId)1696 private int getHalUserInfoFlags(@UserIdInt int userId) { 1697 UserHandle user = mUserHandleHelper.getExistingUserHandle(userId); 1698 Preconditions.checkArgument(user != null, "no user for id %d", userId); 1699 return UserHalHelper.convertFlags(mUserHandleHelper, user); 1700 } 1701 sendUserSwitchResult(@onNull ResultCallbackImpl<UserSwitchResult> callback, boolean isLogout, @UserSwitchResult.Status int userSwitchStatus)1702 static void sendUserSwitchResult(@NonNull ResultCallbackImpl<UserSwitchResult> callback, 1703 boolean isLogout, @UserSwitchResult.Status int userSwitchStatus) { 1704 sendUserSwitchResult(callback, isLogout, HalCallback.STATUS_INVALID, userSwitchStatus, 1705 /* androidFailureStatus= */ null, /* errorMessage= */ null); 1706 } 1707 sendUserSwitchResult(@onNull ResultCallbackImpl<UserSwitchResult> callback, boolean isLogout, @HalCallback.HalCallbackStatus int halCallbackStatus, @UserSwitchResult.Status int userSwitchStatus, @Nullable Integer androidFailureStatus, @Nullable String errorMessage)1708 static void sendUserSwitchResult(@NonNull ResultCallbackImpl<UserSwitchResult> callback, 1709 boolean isLogout, @HalCallback.HalCallbackStatus int halCallbackStatus, 1710 @UserSwitchResult.Status int userSwitchStatus, @Nullable Integer androidFailureStatus, 1711 @Nullable String errorMessage) { 1712 if (isLogout) { 1713 EventLogHelper.writeCarUserServiceLogoutUserResp(halCallbackStatus, userSwitchStatus, 1714 errorMessage); 1715 } else { 1716 EventLogHelper.writeCarUserServiceSwitchUserResp(halCallbackStatus, userSwitchStatus, 1717 errorMessage); 1718 } 1719 callback.complete( 1720 new UserSwitchResult(userSwitchStatus, androidFailureStatus, errorMessage)); 1721 } 1722 sendUserCreationFailure(ResultCallbackImpl<UserCreationResult> callback, @UserCreationResult.Status int status, String internalErrorMessage)1723 void sendUserCreationFailure(ResultCallbackImpl<UserCreationResult> callback, 1724 @UserCreationResult.Status int status, String internalErrorMessage) { 1725 sendUserCreationResult(callback, status, /* androidFailureStatus= */ null, /* user= */ null, 1726 /* errorMessage= */ null, internalErrorMessage); 1727 } 1728 sendUserCreationResult(ResultCallbackImpl<UserCreationResult> callback, @UserCreationResult.Status int status, @Nullable Integer androidFailureStatus, @NonNull UserHandle user, @Nullable String errorMessage, @Nullable String internalErrorMessage)1729 private void sendUserCreationResult(ResultCallbackImpl<UserCreationResult> callback, 1730 @UserCreationResult.Status int status, @Nullable Integer androidFailureStatus, 1731 @NonNull UserHandle user, @Nullable String errorMessage, 1732 @Nullable String internalErrorMessage) { 1733 if (TextUtils.isEmpty(errorMessage)) { 1734 errorMessage = null; 1735 } 1736 if (TextUtils.isEmpty(internalErrorMessage)) { 1737 internalErrorMessage = null; 1738 } 1739 1740 callback.complete(new UserCreationResult(status, androidFailureStatus, user, errorMessage, 1741 internalErrorMessage)); 1742 1743 // When done creating a user, post the next user creation task from the queue, if any. 1744 postNextCreateUserIfAvailable(); 1745 } 1746 1747 /** 1748 * Calls activity manager for user switch. 1749 * 1750 * <p><b>NOTE</b> This method is meant to be called just by UserHalService. 1751 * 1752 * @param requestId for the user switch request 1753 * @param targetUserId of the target user 1754 * 1755 * @hide 1756 */ switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId)1757 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) { 1758 EventLogHelper.writeCarUserServiceSwitchUserFromHalReq(requestId, targetUserId); 1759 Slogf.i(TAG, "User hal requested a user switch. Target user id is %d", targetUserId); 1760 1761 boolean result = mAm.switchUser(UserHandle.of(targetUserId)); 1762 if (result) { 1763 updateUserSwitchInProcess(requestId, targetUserId); 1764 } else { 1765 postSwitchHalResponse(requestId, targetUserId); 1766 } 1767 } 1768 updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId)1769 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) { 1770 synchronized (mLockUser) { 1771 if (mUserIdForUserSwitchInProcess != USER_NULL) { 1772 // Some other user switch is in process. 1773 Slogf.w(TAG, "User switch for user id %d is in process. Abandoning it as a new user" 1774 + " switch is requested for the target user %d", 1775 mUserIdForUserSwitchInProcess, targetUserId); 1776 } 1777 mUserIdForUserSwitchInProcess = targetUserId; 1778 mRequestIdForUserSwitchInProcess = requestId; 1779 } 1780 } 1781 postSwitchHalResponse(int requestId, @UserIdInt int targetUserId)1782 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) { 1783 if (!isUserHalSupported()) return; 1784 1785 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1786 EventLogHelper.writeCarUserServicePostSwitchUserReq(targetUserId, 1787 usersInfo.currentUser.userId); 1788 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo); 1789 request.requestId = requestId; 1790 mHal.postSwitchResponse(request); 1791 } 1792 createUserSwitchRequest(@serIdInt int targetUserId, @NonNull UsersInfo usersInfo)1793 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId, 1794 @NonNull UsersInfo usersInfo) { 1795 UserHandle targetUser = mUserHandleHelper.getExistingUserHandle(targetUserId); 1796 UserInfo halTargetUser = new UserInfo(); 1797 halTargetUser.userId = targetUser.getIdentifier(); 1798 halTargetUser.flags = UserHalHelper.convertFlags(mUserHandleHelper, targetUser); 1799 SwitchUserRequest request = UserHalHelper.emptySwitchUserRequest(); 1800 request.targetUser = halTargetUser; 1801 request.usersInfo = usersInfo; 1802 return request; 1803 } 1804 1805 /** 1806 * Checks if the User HAL is supported. 1807 */ isUserHalSupported()1808 public boolean isUserHalSupported() { 1809 return mHal.isSupported(); 1810 } 1811 1812 /** 1813 * Checks if the User HAL user association is supported. 1814 */ 1815 @Override isUserHalUserAssociationSupported()1816 public boolean isUserHalUserAssociationSupported() { 1817 return mHal.isUserAssociationSupported(); 1818 } 1819 1820 /** 1821 * Sets a callback which is invoked before user switch. 1822 * 1823 * <p> 1824 * This method should only be called by the Car System UI. The purpose of this call is to notify 1825 * Car System UI to show the user switch UI before the user switch. 1826 */ 1827 @Override setUserSwitchUiCallback(@onNull ICarResultReceiver receiver)1828 public void setUserSwitchUiCallback(@NonNull ICarResultReceiver receiver) { 1829 checkManageUsersPermission("setUserSwitchUiCallback"); 1830 1831 // Confirm that caller is system UI. 1832 String systemUiPackageName = PackageManagerHelper.getSystemUiPackageName(mContext); 1833 1834 try { 1835 int systemUiUid = mContext 1836 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager() 1837 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY); 1838 int callerUid = Binder.getCallingUid(); 1839 if (systemUiUid != callerUid) { 1840 throw new SecurityException("Invalid caller. Only" + systemUiPackageName 1841 + " is allowed to make this call"); 1842 } 1843 } catch (NameNotFoundException e) { 1844 throw new IllegalStateException("Package " + systemUiPackageName + " not found", e); 1845 } 1846 1847 mUserSwitchUiReceiver = receiver; 1848 } 1849 updateDefaultUserRestriction()1850 private void updateDefaultUserRestriction() { 1851 // We want to set restrictions on system and guest users only once. These are persisted 1852 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes. 1853 if (Settings.Global.getInt(mContext.getContentResolver(), 1854 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) { 1855 return; 1856 } 1857 // Only apply the system user restrictions if the system user is headless. 1858 if (UserManager.isHeadlessSystemUserMode()) { 1859 setSystemUserRestrictions(); 1860 } 1861 Settings.Global.putInt(mContext.getContentResolver(), 1862 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1); 1863 } 1864 isPersistentUser(@serIdInt int userId)1865 private boolean isPersistentUser(@UserIdInt int userId) { 1866 return !mUserHandleHelper.isEphemeralUser(UserHandle.of(userId)); 1867 } 1868 1869 /** 1870 * Adds a new {@link UserLifecycleListener} with {@code filter} to selectively listen to user 1871 * activity events. 1872 */ addUserLifecycleListener(@ullable UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener)1873 public void addUserLifecycleListener(@Nullable UserLifecycleEventFilter filter, 1874 @NonNull UserLifecycleListener listener) { 1875 Objects.requireNonNull(listener, "listener cannot be null"); 1876 mHandler.post(() -> mUserLifecycleListeners.add( 1877 new InternalLifecycleListener(listener, filter))); 1878 } 1879 1880 /** 1881 * Removes previously added {@link UserLifecycleListener}. 1882 */ removeUserLifecycleListener(@onNull UserLifecycleListener listener)1883 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) { 1884 Objects.requireNonNull(listener, "listener cannot be null"); 1885 mHandler.post(() -> { 1886 for (int i = 0; i < mUserLifecycleListeners.size(); i++) { 1887 if (listener.equals(mUserLifecycleListeners.get(i).listener)) { 1888 mUserLifecycleListeners.remove(i); 1889 } 1890 } 1891 }); 1892 } 1893 onUserUnlocked(@serIdInt int userId)1894 private void onUserUnlocked(@UserIdInt int userId) { 1895 ArrayList<Runnable> tasks = null; 1896 synchronized (mLockUser) { 1897 sendPostSwitchToHalLocked(userId); 1898 if (userId == UserHandle.SYSTEM.getIdentifier()) { 1899 if (!mUser0Unlocked) { // user 0, unlocked, do this only once 1900 updateDefaultUserRestriction(); 1901 tasks = new ArrayList<>(mUser0UnlockTasks); 1902 mUser0UnlockTasks.clear(); 1903 mUser0Unlocked = true; 1904 } 1905 } else { // none user0 1906 Integer user = userId; 1907 if (isPersistentUser(userId)) { 1908 // current foreground user should stay in top priority. 1909 if (userId == ActivityManager.getCurrentUser()) { 1910 mBackgroundUsersToRestart.remove(user); 1911 mBackgroundUsersToRestart.add(0, user); 1912 } 1913 // -1 for user 0 1914 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) { 1915 int userToDrop = mBackgroundUsersToRestart.get( 1916 mBackgroundUsersToRestart.size() - 1); 1917 Slogf.i(TAG, "New user (%d) unlocked, dropping least recently user from " 1918 + "restart list (%s)", userId, userToDrop); 1919 // Drop the least recently used user. 1920 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1); 1921 } 1922 } 1923 } 1924 } 1925 if (tasks != null) { 1926 int tasksSize = tasks.size(); 1927 if (tasksSize > 0) { 1928 Slogf.d(TAG, "User0 unlocked, run queued tasks size: %d", tasksSize); 1929 for (int i = 0; i < tasksSize; i++) { 1930 tasks.get(i).run(); 1931 } 1932 } 1933 } 1934 startUsersOrHomeOnSecondaryDisplays(userId); 1935 } 1936 onUserStarting(@serIdInt int userId)1937 private void onUserStarting(@UserIdInt int userId) { 1938 if (DBG) { 1939 Slogf.d(TAG, "onUserStarting: user %d", userId); 1940 } 1941 1942 if (!isMultipleUsersOnMultipleDisplaysSupported(mUserManager) 1943 || isSystemUserInHeadlessSystemUserMode(userId)) { 1944 return; 1945 } 1946 1947 // Non-current user only 1948 // TODO(b/270719791): Keep track of the current user to avoid IPC to AM. 1949 if (userId == ActivityManager.getCurrentUser()) { 1950 if (DBG) { 1951 Slogf.d(TAG, "onUserStarting: user %d is the current user, skipping", userId); 1952 } 1953 return; 1954 } 1955 1956 // TODO(b/273015292): Handling both "user visible" before "user starting" and 1957 // "user starting" before "user visible" for now because 1958 // UserController / UserVisibilityMediator don't sync the callbacks. 1959 if (isUserVisible(userId)) { 1960 if (DBG) { 1961 Slogf.d(TAG, "onUserStarting: user %d is already visible", userId); 1962 } 1963 1964 // If the user is already visible, do zone assignment and start SysUi. 1965 // This addresses the most common scenario that "user starting" event occurs after 1966 // "user visible" event. 1967 assignVisibleUserToZone(userId); 1968 startSystemUIForVisibleUser(userId); 1969 } else { 1970 // If the user is not visible at this point, they might become visible at a later point. 1971 // So we save this user in 'mNotVisibleAtStartingUsers' for them to be checked in 1972 // onUserVisible. 1973 // This is the first half of addressing the scenario that "user visible" event occurs 1974 // after "user starting" event. 1975 if (DBG) { 1976 Slogf.d(TAG, "onUserStarting: user %d is not visible, " 1977 + "adding to starting user queue", userId); 1978 } 1979 synchronized (mLockUser) { 1980 if (!mNotVisibleAtStartingUsers.contains(userId)) { 1981 mNotVisibleAtStartingUsers.add(userId); 1982 } else { 1983 // This is likely the case that this user started, but never became visible, 1984 // then stopped in the past before starting again and becoming visible. 1985 Slogf.i(TAG, "onUserStarting: user %d might start and stop in the past before " 1986 + "starting again, reusing the user", userId); 1987 } 1988 } 1989 } 1990 } 1991 onUserVisible(@serIdInt int userId)1992 private void onUserVisible(@UserIdInt int userId) { 1993 if (DBG) { 1994 Slogf.d(TAG, "onUserVisible: user %d", userId); 1995 } 1996 1997 // TODO(b/270719791): Keep track of the current user to avoid IPC to AM. 1998 if (!isMultipleUsersOnMultipleDisplaysSupported(mUserManager) 1999 || isSystemUserInHeadlessSystemUserMode(userId)) { 2000 return; 2001 } 2002 2003 // Non-current user only 2004 // TODO(b/270719791): Keep track of the current user to avoid IPC to AM. 2005 if (userId == ActivityManager.getCurrentUser()) { 2006 if (DBG) { 2007 Slogf.d(TAG, "onUserVisible: user %d is the current user, skipping", userId); 2008 } 2009 return; 2010 } 2011 2012 boolean isUserRunning = mUserManager.isUserRunning(UserHandle.of(userId)); 2013 // If the user is found in 'mNotVisibleAtStartingUsers' and is running, 2014 // do occupant zone assignment and start SysUi. 2015 // Then remove the user from the 'mNotVisibleAtStartingUsers'. 2016 // This is the second half of addressing the scenario that "user visible" event occurs after 2017 // "user starting" event. 2018 synchronized (mLockUser) { 2019 if (mNotVisibleAtStartingUsers.contains(userId)) { 2020 if (DBG) { 2021 Slogf.d(TAG, "onUserVisible: found user %d in the list of users not visible at" 2022 + " starting", userId); 2023 } 2024 if (!isUserRunning) { 2025 if (DBG) { 2026 Slogf.d(TAG, "onUserVisible: user %d is not running", userId); 2027 } 2028 // If the user found in 'mNotVisibleAtStartingUsers' is not running, 2029 // this is likely the case that this user started, but never became visible, 2030 // then stopped in the past before becoming visible and starting again. 2031 // Take this opportunity to clean this user up. 2032 mNotVisibleAtStartingUsers.remove(Integer.valueOf(userId)); 2033 return; 2034 } 2035 2036 // If the user found in 'mNotVisibleAtStartingUsers' is running, this is the case 2037 // that user starting occurred earlier than user visible. 2038 if (DBG) { 2039 Slogf.d(TAG, "onUserVisible: assigning user %d to occupant zone and starting " 2040 + "SysUi.", userId); 2041 } 2042 assignVisibleUserToZone(userId); 2043 startSystemUIForVisibleUser(userId); 2044 // The user will be cleared from 'mNotVisibleAtStartingUsers' the first time it 2045 // becomes visible since starting. 2046 mNotVisibleAtStartingUsers.remove(Integer.valueOf(userId)); 2047 } 2048 } 2049 } 2050 onUserInvisible(@serIdInt int userId)2051 private void onUserInvisible(@UserIdInt int userId) { 2052 if (!isMultipleUsersOnMultipleDisplaysSupported(mUserManager)) { 2053 return; 2054 } 2055 2056 if (isSystemUserInHeadlessSystemUserMode(userId)) { 2057 return; 2058 } 2059 2060 stopSystemUiForUser(mContext, userId); 2061 unassignInvisibleUserFromZone(userId); 2062 } 2063 startUsersOrHomeOnSecondaryDisplays(@serIdInt int userId)2064 private void startUsersOrHomeOnSecondaryDisplays(@UserIdInt int userId) { 2065 if (!isMultipleUsersOnMultipleDisplaysSupported(mUserManager)) { 2066 if (DBG) { 2067 Slogf.d(TAG, "startUsersOrHomeOnSecondaryDisplays(%d): not supported", userId); 2068 } 2069 return; 2070 } 2071 2072 // Run from here only when CMUMD is supported. 2073 if (userId == ActivityManager.getCurrentUser()) { 2074 mBgHandler.post(() -> startUserPickerOnOtherDisplays(/* currentUserId= */ userId)); 2075 } else { 2076 mBgHandler.post(() -> startLauncherForVisibleUser(userId)); 2077 } 2078 } 2079 2080 /** 2081 * Starts the specified user. 2082 * 2083 * <p>If a valid display ID is specified in the {@code request}, then start the user visible on 2084 * the display. 2085 */ 2086 @Override startUser(UserStartRequest request, ResultCallbackImpl<UserStartResponse> callback)2087 public void startUser(UserStartRequest request, 2088 ResultCallbackImpl<UserStartResponse> callback) { 2089 if (!hasManageUsersOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)) { 2090 throw new SecurityException("startUser: You need one of " + MANAGE_USERS 2091 + ", or " + INTERACT_ACROSS_USERS); 2092 } 2093 int userId = request.getUserHandle().getIdentifier(); 2094 int displayId = request.getDisplayId(); 2095 if (isPlatformVersionAtLeastU()) { 2096 EventLogHelper.writeCarUserServiceStartUserVisibleOnDisplayReq(userId, displayId); 2097 } else { 2098 EventLogHelper.writeCarUserServiceStartUserInBackgroundReq(userId); 2099 } 2100 mHandler.post(() -> handleStartUser(userId, displayId, callback)); 2101 } 2102 handleStartUser(@serIdInt int userId, int displayId, ResultCallbackImpl<UserStartResponse> callback)2103 private void handleStartUser(@UserIdInt int userId, int displayId, 2104 ResultCallbackImpl<UserStartResponse> callback) { 2105 @UserStartResponse.Status int userStartStatus = startUserInternal(userId, displayId); 2106 sendUserStartUserResponse(userId, displayId, userStartStatus, callback); 2107 } 2108 sendUserStartUserResponse(@serIdInt int userId, int displayId, @UserStartResponse.Status int result, @NonNull ResultCallbackImpl<UserStartResponse> callback)2109 private void sendUserStartUserResponse(@UserIdInt int userId, int displayId, 2110 @UserStartResponse.Status int result, 2111 @NonNull ResultCallbackImpl<UserStartResponse> callback) { 2112 if (isPlatformVersionAtLeastU()) { 2113 EventLogHelper.writeCarUserServiceStartUserVisibleOnDisplayResp(userId, displayId, 2114 result); 2115 } else { 2116 EventLogHelper.writeCarUserServiceStartUserInBackgroundResp(userId, result); 2117 } 2118 callback.complete(new UserStartResponse(result)); 2119 } 2120 startUserInternal(@serIdInt int userId, int displayId)2121 private @UserStartResponse.Status int startUserInternal(@UserIdInt int userId, int displayId) { 2122 if (displayId == Display.INVALID_DISPLAY) { 2123 // For an invalid display ID, start the user in background without a display. 2124 int status = startUserInBackgroundInternal(userId); 2125 // This works because the status code of UserStartResponse is a superset of 2126 // UserStartResult. 2127 return status; 2128 } 2129 2130 if (!isPlatformVersionAtLeastU()) { 2131 Slogf.w(TAG, "The platform does not support startUser." 2132 + " Platform version: %s", Car.getPlatformVersion()); 2133 return UserStartResponse.STATUS_UNSUPPORTED_PLATFORM_FAILURE; 2134 } 2135 2136 // If the requested user is the system user. 2137 if (userId == UserHandle.SYSTEM.getIdentifier()) { 2138 return UserStartResponse.STATUS_USER_INVALID; 2139 } 2140 // If the requested user does not exist. 2141 if (mUserHandleHelper.getExistingUserHandle(userId) == null) { 2142 return UserStartResponse.STATUS_USER_DOES_NOT_EXIST; 2143 } 2144 2145 // If the specified display is not a valid display for assigning user to. 2146 // Note: In passenger only system, users will be allowed on the DEFAULT_DISPLAY. 2147 if (displayId == Display.DEFAULT_DISPLAY) { 2148 if (!mIsVisibleBackgroundUsersOnDefaultDisplaySupported) { 2149 return UserStartResponse.STATUS_DISPLAY_INVALID; 2150 } else { 2151 if (DBG) { 2152 Slogf.d(TAG, "startUserVisibleOnDisplayInternal: allow starting user on the " 2153 + "default display under Multi User No Driver mode"); 2154 } 2155 } 2156 } 2157 // If the specified display is not available to start a user on. 2158 if (mCarOccupantZoneService.getUserForDisplayId(displayId) 2159 != CarOccupantZoneManager.INVALID_USER_ID) { 2160 return UserStartResponse.STATUS_DISPLAY_UNAVAILABLE; 2161 } 2162 2163 int curDisplayIdAssignedToUser = getMainDisplayAssignedToUser(userId); 2164 if (curDisplayIdAssignedToUser == displayId) { 2165 // If the user is already visible on the display, do nothing and return success. 2166 return UserStartResponse.STATUS_SUCCESSFUL_USER_ALREADY_VISIBLE_ON_DISPLAY; 2167 } 2168 if (curDisplayIdAssignedToUser != Display.INVALID_DISPLAY) { 2169 // If the specified user is assigned to another display, the user has to be stopped 2170 // before it can start on another display. 2171 return UserStartResponse.STATUS_USER_ASSIGNED_TO_ANOTHER_DISPLAY; 2172 } 2173 2174 return ActivityManagerHelper.startUserInBackgroundVisibleOnDisplay(userId, displayId) 2175 ? UserStartResponse.STATUS_SUCCESSFUL : UserStartResponse.STATUS_ANDROID_FAILURE; 2176 } 2177 2178 /** 2179 * Starts the specified user in the background. 2180 * 2181 * @param userId user to start in background 2182 * @param receiver to post results 2183 */ startUserInBackground(@serIdInt int userId, @NonNull AndroidFuture<UserStartResult> receiver)2184 public void startUserInBackground(@UserIdInt int userId, 2185 @NonNull AndroidFuture<UserStartResult> receiver) { 2186 checkManageOrCreateUsersPermission("startUserInBackground"); 2187 EventLogHelper.writeCarUserServiceStartUserInBackgroundReq(userId); 2188 2189 mHandler.post(() -> handleStartUserInBackground(userId, receiver)); 2190 } 2191 handleStartUserInBackground(@serIdInt int userId, AndroidFuture<UserStartResult> receiver)2192 private void handleStartUserInBackground(@UserIdInt int userId, 2193 AndroidFuture<UserStartResult> receiver) { 2194 int result = startUserInBackgroundInternal(userId); 2195 sendUserStartResult(userId, result, receiver); 2196 } 2197 startUserInBackgroundInternal(@serIdInt int userId)2198 private @UserStartResult.Status int startUserInBackgroundInternal(@UserIdInt int userId) { 2199 // If the requested user is the current user, do nothing and return success. 2200 if (ActivityManager.getCurrentUser() == userId) { 2201 return UserStartResult.STATUS_SUCCESSFUL_USER_IS_CURRENT_USER; 2202 } 2203 // If requested user does not exist, return error. 2204 if (mUserHandleHelper.getExistingUserHandle(userId) == null) { 2205 Slogf.w(TAG, "User %d does not exist", userId); 2206 return UserStartResult.STATUS_USER_DOES_NOT_EXIST; 2207 } 2208 2209 if (!ActivityManagerHelper.startUserInBackground(userId)) { 2210 Slogf.w(TAG, "Failed to start user %d in background", userId); 2211 return UserStartResult.STATUS_ANDROID_FAILURE; 2212 } 2213 2214 // TODO(b/181331178): We are not updating mBackgroundUsersToRestart or 2215 // mBackgroundUsersRestartedHere, which were only used for the garage mode. Consider 2216 // renaming them to make it more clear. 2217 return UserStartResult.STATUS_SUCCESSFUL; 2218 } 2219 sendUserStartResult(@serIdInt int userId, @UserStartResult.Status int result, @NonNull AndroidFuture<UserStartResult> receiver)2220 private void sendUserStartResult(@UserIdInt int userId, @UserStartResult.Status int result, 2221 @NonNull AndroidFuture<UserStartResult> receiver) { 2222 EventLogHelper.writeCarUserServiceStartUserInBackgroundResp(userId, result); 2223 receiver.complete(new UserStartResult(result)); 2224 } 2225 2226 /** 2227 * Starts all background users that were active in system. 2228 * 2229 * @return list of background users started successfully. 2230 */ 2231 @NonNull startAllBackgroundUsersInGarageMode()2232 public ArrayList<Integer> startAllBackgroundUsersInGarageMode() { 2233 synchronized (mLockUser) { 2234 if (!mStartBackgroundUsersOnGarageMode) { 2235 Slogf.i(TAG, "Background users are not started as mStartBackgroundUsersOnGarageMode" 2236 + " is false."); 2237 return new ArrayList<>(); 2238 } 2239 } 2240 2241 ArrayList<Integer> users; 2242 synchronized (mLockUser) { 2243 users = new ArrayList<>(mBackgroundUsersToRestart); 2244 mBackgroundUsersRestartedHere.clear(); 2245 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart); 2246 } 2247 ArrayList<Integer> startedUsers = new ArrayList<>(); 2248 for (Integer user : users) { 2249 if (user == ActivityManager.getCurrentUser()) { 2250 continue; 2251 } 2252 if (ActivityManagerHelper.startUserInBackground(user)) { 2253 if (mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user))) { 2254 // already unlocked / unlocking. No need to unlock. 2255 startedUsers.add(user); 2256 } else if (ActivityManagerHelper.unlockUser(user)) { 2257 startedUsers.add(user); 2258 } else { // started but cannot unlock 2259 Slogf.w(TAG, "Background user started but cannot be unlocked: %s", user); 2260 if (mUserManager.isUserRunning(UserHandle.of(user))) { 2261 // add to started list so that it can be stopped later. 2262 startedUsers.add(user); 2263 } 2264 } 2265 } 2266 } 2267 // Keep only users that were re-started in mBackgroundUsersRestartedHere 2268 synchronized (mLockUser) { 2269 ArrayList<Integer> usersToRemove = new ArrayList<>(); 2270 for (Integer user : mBackgroundUsersToRestart) { 2271 if (!startedUsers.contains(user)) { 2272 usersToRemove.add(user); 2273 } 2274 } 2275 mBackgroundUsersRestartedHere.removeAll(usersToRemove); 2276 } 2277 return startedUsers; 2278 } 2279 2280 /** 2281 * Stops the specified background user. 2282 * 2283 * @param userId user to stop 2284 * @param receiver to post results 2285 * 2286 * @deprecated Use {@link #stopUser(UserStopRequest, ResultCallbackImpl<UserStopResponse>)} 2287 * instead. 2288 */ 2289 // TODO(b/279793766) Clean up this method. stopUser(@serIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver)2290 public void stopUser(@UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) { 2291 checkManageOrCreateUsersPermission("stopUser"); 2292 EventLogHelper.writeCarUserServiceStopUserReq(userId); 2293 2294 mHandler.post(() -> handleStopUser(userId, receiver)); 2295 } 2296 handleStopUser(@serIdInt int userId, AndroidFuture<UserStopResult> receiver)2297 private void handleStopUser(@UserIdInt int userId, AndroidFuture<UserStopResult> receiver) { 2298 @UserStopResult.Status int result = stopBackgroundUserInternal(userId, 2299 /* forceStop= */ true, /* withDelayedLocking= */ true); 2300 EventLogHelper.writeCarUserServiceStopUserResp(userId, result); 2301 receiver.complete(new UserStopResult(result)); 2302 } 2303 2304 /** 2305 * Stops the specified background user. 2306 */ 2307 @Override stopUser(UserStopRequest request, ResultCallbackImpl<UserStopResponse> callback)2308 public void stopUser(UserStopRequest request, 2309 ResultCallbackImpl<UserStopResponse> callback) { 2310 if (!hasManageUsersOrPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)) { 2311 throw new SecurityException("stopUser: You need one of " + MANAGE_USERS + ", or " 2312 + INTERACT_ACROSS_USERS); 2313 } 2314 int userId = request.getUserHandle().getIdentifier(); 2315 boolean withDelayedLocking = request.isWithDelayedLocking(); 2316 boolean forceStop = request.isForce(); 2317 EventLogHelper.writeCarUserServiceStopUserReq(userId); 2318 mHandler.post(() -> handleStopUser(userId, forceStop, withDelayedLocking, callback)); 2319 } 2320 handleStopUser(@serIdInt int userId, boolean forceStop, boolean withDelayedLocking, ResultCallbackImpl<UserStopResponse> callback)2321 private void handleStopUser(@UserIdInt int userId, boolean forceStop, 2322 boolean withDelayedLocking, ResultCallbackImpl<UserStopResponse> callback) { 2323 @UserStopResponse.Status int userStopStatus = 2324 stopBackgroundUserInternal(userId, forceStop, withDelayedLocking); 2325 sendUserStopResult(userId, userStopStatus, callback); 2326 } 2327 sendUserStopResult(@serIdInt int userId, @UserStopResponse.Status int result, ResultCallbackImpl<UserStopResponse> callback)2328 private void sendUserStopResult(@UserIdInt int userId, @UserStopResponse.Status int result, 2329 ResultCallbackImpl<UserStopResponse> callback) { 2330 EventLogHelper.writeCarUserServiceStopUserResp(userId, result); 2331 callback.complete(new UserStopResponse(result)); 2332 } 2333 stopBackgroundUserInternal(@serIdInt int userId, boolean forceStop, boolean withDelayedLocking)2334 private @UserStopResult.Status int stopBackgroundUserInternal(@UserIdInt int userId, 2335 boolean forceStop, boolean withDelayedLocking) { 2336 int r; 2337 try { 2338 if (withDelayedLocking) { 2339 r = ActivityManagerHelper.stopUserWithDelayedLocking(userId, forceStop); 2340 } else if (isPlatformVersionAtLeastU()) { 2341 r = ActivityManagerHelper.stopUser(userId, forceStop); 2342 } else { 2343 Slogf.w(TAG, "stopUser() without delayed locking is not supported " 2344 + " in older platform version"); 2345 return UserStopResult.STATUS_ANDROID_FAILURE; 2346 } 2347 } catch (RuntimeException e) { 2348 Slogf.e(TAG, e, "Exception calling am.stopUser(%d, true)", userId); 2349 return UserStopResult.STATUS_ANDROID_FAILURE; 2350 } 2351 switch(r) { 2352 case USER_OP_SUCCESS: 2353 return UserStopResult.STATUS_SUCCESSFUL; 2354 case USER_OP_ERROR_IS_SYSTEM: 2355 Slogf.w(TAG, "Cannot stop the system user: %d", userId); 2356 return UserStopResult.STATUS_FAILURE_SYSTEM_USER; 2357 case USER_OP_IS_CURRENT: 2358 Slogf.w(TAG, "Cannot stop the current user: %d", userId); 2359 return UserStopResult.STATUS_FAILURE_CURRENT_USER; 2360 case USER_OP_UNKNOWN_USER: 2361 Slogf.w(TAG, "Cannot stop the user that does not exist: %d", userId); 2362 return UserStopResult.STATUS_USER_DOES_NOT_EXIST; 2363 default: 2364 Slogf.w(TAG, "stopUser failed, user: %d, err: %d", userId, r); 2365 } 2366 return UserStopResult.STATUS_ANDROID_FAILURE; 2367 } 2368 2369 /** 2370 * Sets boolean to control background user operations during garage mode. 2371 */ setStartBackgroundUsersOnGarageMode(boolean enable)2372 public void setStartBackgroundUsersOnGarageMode(boolean enable) { 2373 synchronized (mLockUser) { 2374 mStartBackgroundUsersOnGarageMode = enable; 2375 } 2376 } 2377 2378 /** 2379 * Stops a background user. 2380 * 2381 * @return whether stopping succeeds. 2382 */ stopBackgroundUserInGagageMode(@serIdInt int userId)2383 public boolean stopBackgroundUserInGagageMode(@UserIdInt int userId) { 2384 synchronized (mLockUser) { 2385 if (!mStartBackgroundUsersOnGarageMode) { 2386 Slogf.i(TAG, "Background users are not stopped as mStartBackgroundUsersOnGarageMode" 2387 + " is false."); 2388 return false; 2389 } 2390 } 2391 2392 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId, 2393 /* forceStop= */ true, /* withDelayedLocking= */ true); 2394 if (UserStopResult.isSuccess(userStopStatus)) { 2395 // Remove the stopped user from the mBackgroundUserRestartedHere list. 2396 synchronized (mLockUser) { 2397 mBackgroundUsersRestartedHere.remove(Integer.valueOf(userId)); 2398 } 2399 return true; 2400 } 2401 return false; 2402 } 2403 2404 /** 2405 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument. 2406 */ onUserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int fromUserId, @UserIdInt int toUserId)2407 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType, 2408 @UserIdInt int fromUserId, @UserIdInt int toUserId) { 2409 if (DBG) { 2410 Slogf.d(TAG, "onUserLifecycleEvent(): event=%d, from=%d, to=%d", eventType, fromUserId, 2411 toUserId); 2412 } 2413 if (!isPlatformVersionAtLeastU() 2414 && (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_VISIBLE 2415 || eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_INVISIBLE)) { 2416 // UserVisibilityChanged events are not supported before U. 2417 Slogf.w(TAG, "Ignoring unsupported user lifecycle event: type %d, user %d", 2418 eventType, toUserId); 2419 return; 2420 } 2421 int userId = toUserId; 2422 2423 // Handle special cases first... 2424 switch (eventType) { 2425 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING: 2426 onUserSwitching(fromUserId, toUserId); 2427 break; 2428 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED: 2429 onUserUnlocked(userId); 2430 break; 2431 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_REMOVED: 2432 onUserRemoved(UserHandle.of(userId)); 2433 break; 2434 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING: 2435 onUserStarting(userId); 2436 break; 2437 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_VISIBLE: 2438 onUserVisible(userId); 2439 break; 2440 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_INVISIBLE: 2441 onUserInvisible(userId); 2442 break; 2443 default: 2444 } 2445 2446 // ...then notify listeners. 2447 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId); 2448 2449 mHandler.post(() -> { 2450 handleNotifyServiceUserLifecycleListeners(event); 2451 // POST_UNLOCKED event is meant only for internal service listeners. Skip sending it to 2452 // app listeners. 2453 if (eventType != CarUserManager.USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED) { 2454 handleNotifyAppUserLifecycleListeners(event); 2455 } 2456 }); 2457 } 2458 2459 // value format: , separated zoneId:userId 2460 @VisibleForTesting parseUserAssignmentSettingValue(String settingKey, String value)2461 SparseIntArray parseUserAssignmentSettingValue(String settingKey, String value) { 2462 Slogf.d(TAG, "Use %s for starting users", settingKey); 2463 SparseIntArray mapping = new SparseIntArray(); 2464 try { 2465 String[] entries = value.split(","); 2466 for (String entry : entries) { 2467 String[] pair = entry.split(":"); 2468 if (pair.length != 2) { 2469 throw new IllegalArgumentException("Expecting zoneId:userId"); 2470 } 2471 int zoneId = Integer.parseInt(pair[0]); 2472 int userId = Integer.parseInt(pair[1]); 2473 if (mapping.indexOfKey(zoneId) >= 0) { 2474 throw new IllegalArgumentException("Multiple use of zone id:" + zoneId); 2475 } 2476 if (mapping.indexOfValue(userId) >= 0) { 2477 throw new IllegalArgumentException("Multiple use of user id:" + userId); 2478 } 2479 mapping.append(zoneId, userId); 2480 } 2481 } catch (Exception e) { 2482 Slogf.w(TAG, e, "Setting %s has invalid value: ", settingKey, value); 2483 // Parsing error, ignore all. 2484 mapping.clear(); 2485 } 2486 return mapping; 2487 } 2488 isSystemUserInHeadlessSystemUserMode(@serIdInt int userId)2489 private boolean isSystemUserInHeadlessSystemUserMode(@UserIdInt int userId) { 2490 return userId == UserHandle.SYSTEM.getIdentifier() 2491 && mUserManager.isHeadlessSystemUserMode(); 2492 } 2493 2494 // starts user picker on displays without user allocation exception for on driver main display. startUserPicker()2495 void startUserPicker() { 2496 int driverZoneId = OccupantZoneInfo.INVALID_ZONE_ID; 2497 boolean hasDriverZone = mCarOccupantZoneService.hasDriverZone(); 2498 if (hasDriverZone) { 2499 driverZoneId = mCarOccupantZoneService.getOccupantZone( 2500 CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER, 2501 VehicleAreaSeat.SEAT_UNKNOWN).zoneId; 2502 } 2503 2504 // Start user picker on displays without user allocation. 2505 List<OccupantZoneInfo> occupantZoneInfos = 2506 mCarOccupantZoneService.getAllOccupantZones(); 2507 for (int i = 0; i < occupantZoneInfos.size(); i++) { 2508 OccupantZoneInfo occupantZoneInfo = occupantZoneInfos.get(i); 2509 int zoneId = occupantZoneInfo.zoneId; 2510 // Skip driver zone when the driver zone exists. 2511 if (hasDriverZone && zoneId == driverZoneId) { 2512 continue; 2513 } 2514 2515 int userId = mCarOccupantZoneService.getUserForOccupant(zoneId); 2516 if (userId != CarOccupantZoneManager.INVALID_USER_ID) { 2517 // If there is already a user allocated to the zone, skip. 2518 continue; 2519 } 2520 2521 int displayId = mCarOccupantZoneService.getDisplayForOccupant(zoneId, 2522 CarOccupantZoneManager.DISPLAY_TYPE_MAIN); 2523 if (displayId == Display.INVALID_DISPLAY) { 2524 Slogf.e(TAG, "No main display for occupant zone:%d", zoneId); 2525 continue; 2526 } 2527 CarLocalServices.getService(CarActivityService.class) 2528 .startUserPickerOnDisplay(displayId); 2529 } 2530 } 2531 2532 @VisibleForTesting startUserPickerOnOtherDisplays(@serIdInt int currentUserId)2533 void startUserPickerOnOtherDisplays(@UserIdInt int currentUserId) { 2534 if (!isMultipleUsersOnMultipleDisplaysSupported(mUserManager)) { 2535 return; 2536 } 2537 if (isSystemUserInHeadlessSystemUserMode(currentUserId) 2538 && !mIsVisibleBackgroundUsersOnDefaultDisplaySupported) { 2539 return; 2540 } 2541 2542 startUserPicker(); 2543 } 2544 2545 // Assigns the non-current visible user to the occupant zone that has the display the user is 2546 // on. assignVisibleUserToZone(@serIdInt int userId)2547 private void assignVisibleUserToZone(@UserIdInt int userId) { 2548 2549 int displayId = getMainDisplayAssignedToUser(userId); 2550 if (displayId == Display.INVALID_DISPLAY) { 2551 Slogf.w(TAG, "Cannot get display assigned to visible user %d", userId); 2552 return; 2553 } 2554 2555 OccupantZoneInfo zoneInfo = getOccupantZoneForDisplayId(displayId); 2556 if (zoneInfo == null) { 2557 Slogf.w(TAG, "Cannot get occupant zone info associated with display %d for user %d", 2558 displayId, userId); 2559 return; 2560 } 2561 2562 int zoneId = zoneInfo.zoneId; 2563 int assignResult = mCarOccupantZoneService.assignVisibleUserToOccupantZone(zoneId, 2564 UserHandle.of(userId)); 2565 if (assignResult != CarOccupantZoneManager.USER_ASSIGNMENT_RESULT_OK) { 2566 Slogf.w(TAG, 2567 "assignVisibleUserToZone: failed to assign user %d to zone %d, result %d", 2568 userId, zoneId, assignResult); 2569 stopUser(userId, new AndroidFuture<UserStopResult>()); 2570 return; 2571 } 2572 } 2573 2574 // Unassigns the invisible user from the occupant zone. unassignInvisibleUserFromZone(@serIdInt int userId)2575 private void unassignInvisibleUserFromZone(@UserIdInt int userId) { 2576 CarOccupantZoneManager.OccupantZoneInfo zoneInfo = 2577 mCarOccupantZoneService.getOccupantZoneForUser(UserHandle.of(userId)); 2578 if (zoneInfo == null) { 2579 Slogf.e(TAG, "unassignInvisibleUserFromZone: cannot find occupant zone for user %d", 2580 userId); 2581 return; 2582 } 2583 2584 int result = mCarOccupantZoneService.unassignOccupantZone(zoneInfo.zoneId); 2585 if (result != CarOccupantZoneManager.USER_ASSIGNMENT_RESULT_OK) { 2586 Slogf.e(TAG, 2587 "unassignInvisibleUserFromZone: failed to unassign user %d from zone %d," 2588 + " result %d", 2589 userId, zoneInfo.zoneId, result); 2590 } 2591 } 2592 2593 /** Should be called for non-current user only */ startSystemUIForVisibleUser(@serIdInt int userId)2594 private void startSystemUIForVisibleUser(@UserIdInt int userId) { 2595 if (!isMultipleUsersOnMultipleDisplaysSupported(mUserManager)) { 2596 return; 2597 } 2598 if (userId == UserHandle.SYSTEM.getIdentifier() 2599 || userId == ActivityManager.getCurrentUser()) { 2600 Slogf.w(TAG, "Cannot start SystemUI for current or system user (userId=%d)", userId); 2601 return; 2602 } 2603 2604 if (isVisibleBackgroundUsersOnDefaultDisplaySupported(mUserManager)) { 2605 int displayId = getMainDisplayAssignedToUser(userId); 2606 if (displayId == Display.DEFAULT_DISPLAY) { 2607 // System user SystemUI is responsible for users running on the default display 2608 Slogf.d(TAG, "Skipping starting SystemUI for passenger user %d on default display", 2609 userId); 2610 return; 2611 } 2612 } 2613 startSystemUiForUser(mContext, userId); 2614 } 2615 2616 /** Should be called for non-current user only */ startLauncherForVisibleUser(@serIdInt int userId)2617 private void startLauncherForVisibleUser(@UserIdInt int userId) { 2618 if (!isMultipleUsersOnMultipleDisplaysSupported(mUserManager)) { 2619 return; 2620 } 2621 if (isSystemUserInHeadlessSystemUserMode(userId)) { 2622 return; 2623 } 2624 2625 int displayId = getMainDisplayAssignedToUser(userId); 2626 if (displayId == Display.INVALID_DISPLAY) { 2627 Slogf.w(TAG, "Cannot get display assigned to visible user %d", userId); 2628 return; 2629 } 2630 2631 boolean result = startHomeForUserAndDisplay(mContext, userId, displayId); 2632 if (!result) { 2633 Slogf.w(TAG, 2634 "Cannot launch home for assigned user %d, display %d, will stop the user", 2635 userId, displayId); 2636 stopUser(userId, new AndroidFuture<UserStopResult>()); 2637 } 2638 } 2639 sendPostSwitchToHalLocked(@serIdInt int userId)2640 private void sendPostSwitchToHalLocked(@UserIdInt int userId) { 2641 int userIdForUserSwitchInProcess; 2642 int requestIdForUserSwitchInProcess; 2643 synchronized (mLockUser) { 2644 if (mUserIdForUserSwitchInProcess == USER_NULL 2645 || mUserIdForUserSwitchInProcess != userId 2646 || mRequestIdForUserSwitchInProcess == 0) { 2647 Slogf.d(TAG, "No user switch request Id. No android post switch sent."); 2648 return; 2649 } 2650 userIdForUserSwitchInProcess = mUserIdForUserSwitchInProcess; 2651 requestIdForUserSwitchInProcess = mRequestIdForUserSwitchInProcess; 2652 2653 mUserIdForUserSwitchInProcess = USER_NULL; 2654 mRequestIdForUserSwitchInProcess = 0; 2655 } 2656 postSwitchHalResponse(requestIdForUserSwitchInProcess, userIdForUserSwitchInProcess); 2657 } 2658 handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event)2659 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) { 2660 int listenersSize = mAppLifecycleListeners.size(); 2661 if (listenersSize == 0) { 2662 Slogf.d(TAG, "No app listener to be notified of %s", event); 2663 return; 2664 } 2665 // Must use a different TimingsTraceLog because it's another thread 2666 if (DBG) { 2667 Slogf.d(TAG, "Notifying %d app listeners of %s", listenersSize, event); 2668 } 2669 int userId = event.getUserId(); 2670 TimingsTraceLog t = new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE); 2671 int eventType = event.getEventType(); 2672 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType); 2673 for (int i = 0; i < listenersSize; i++) { 2674 AppLifecycleListener listener = mAppLifecycleListeners.valueAt(i); 2675 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_CREATED 2676 || eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_REMOVED) { 2677 PlatformVersion platformVersion = Car.getPlatformVersion(); 2678 // Perform platform version check to ensure the support for these new events 2679 // is consistent with the platform version declared in their ApiRequirements. 2680 if (!platformVersion.isAtLeast(PlatformVersion.VERSION_CODES.TIRAMISU_1)) { 2681 if (DBG) { 2682 Slogf.d(TAG, "Skipping app listener %s for event %s due to unsupported" 2683 + " car platform version %s.", listener, event, platformVersion); 2684 } 2685 continue; 2686 } 2687 // Perform target car version check to ensure only apps expecting the new 2688 // lifecycle event types will have the events sent to them. 2689 // TODO(b/235524989): Cache the target car version for packages in 2690 // CarPackageManagerService. 2691 CarVersion targetCarVersion = mCarPackageManagerService.getTargetCarVersion( 2692 listener.packageName); 2693 if (!targetCarVersion.isAtLeast(CarVersion.VERSION_CODES.TIRAMISU_1)) { 2694 if (DBG) { 2695 Slogf.d(TAG, "Skipping app listener %s for event %s due to incompatible" 2696 + " target car version %s.", listener, event, targetCarVersion); 2697 } 2698 continue; 2699 } 2700 } 2701 if (!listener.applyFilters(event)) { 2702 if (DBG) { 2703 Slogf.d(TAG, "Skipping app listener %s for event %s due to the filters" 2704 + " evaluated to false.", listener, event); 2705 } 2706 continue; 2707 } 2708 Bundle data = new Bundle(); 2709 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType); 2710 2711 int fromUserId = event.getPreviousUserId(); 2712 if (fromUserId != USER_NULL) { 2713 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId); 2714 } 2715 Slogf.d(TAG, "Notifying app listener %s", listener); 2716 EventLogHelper.writeCarUserServiceNotifyAppLifecycleListener(listener.uid, 2717 listener.packageName, eventType, fromUserId, userId); 2718 try { 2719 t.traceBegin("notify-app-listener-" + listener.toShortString()); 2720 listener.receiver.send(userId, data); 2721 } catch (RemoteException e) { 2722 Slogf.e(TAG, e, "Error calling lifecycle listener %s", listener); 2723 } finally { 2724 t.traceEnd(); 2725 } 2726 } 2727 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE 2728 } 2729 handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event)2730 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) { 2731 TimingsTraceLog t = new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE); 2732 if (mUserLifecycleListeners.isEmpty()) { 2733 Slogf.w(TAG, "No internal UserLifecycleListeners registered to notify event %s", 2734 event); 2735 return; 2736 } 2737 int userId = event.getUserId(); 2738 int eventType = event.getEventType(); 2739 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType); 2740 for (InternalLifecycleListener listener : mUserLifecycleListeners) { 2741 String listenerName = FunctionalUtils.getLambdaName(listener); 2742 UserLifecycleEventFilter filter = listener.filter; 2743 if (filter != null && !filter.apply(event)) { 2744 if (DBG) { 2745 Slogf.d(TAG, "Skipping service listener %s for event %s due to the filter %s" 2746 + " evaluated to false", listenerName, event, filter); 2747 } 2748 continue; 2749 } 2750 if (DBG) { 2751 Slogf.d(TAG, "Notifying %d service listeners of %s", mUserLifecycleListeners.size(), 2752 event); 2753 } 2754 EventLogHelper.writeCarUserServiceNotifyInternalLifecycleListener(listenerName, 2755 eventType, event.getPreviousUserId(), userId); 2756 try { 2757 t.traceBegin("notify-listener-" + listenerName); 2758 listener.listener.onEvent(event); 2759 } catch (RuntimeException e) { 2760 Slogf.e(TAG, e , "Exception raised when invoking onEvent for %s", listenerName); 2761 } finally { 2762 t.traceEnd(); 2763 } 2764 } 2765 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE 2766 } 2767 onUserSwitching(@serIdInt int fromUserId, @UserIdInt int toUserId)2768 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) { 2769 if (DBG) { 2770 Slogf.i(TAG, "onUserSwitching(from=%d, to=%d)", fromUserId, toUserId); 2771 } 2772 TimingsTraceLog t = new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE); 2773 t.traceBegin("onUserSwitching-" + toUserId); 2774 2775 notifyLegacyUserSwitch(fromUserId, toUserId); 2776 2777 mInitialUserSetter.setLastActiveUser(toUserId); 2778 2779 t.traceEnd(); 2780 } 2781 notifyLegacyUserSwitch(@serIdInt int fromUserId, @UserIdInt int toUserId)2782 private void notifyLegacyUserSwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) { 2783 if (DBG) { 2784 Slogf.d(TAG, "notifyLegacyUserSwitch(%d, %d): mUserIdForUserSwitchInProcess=%d", 2785 fromUserId, toUserId, mUserIdForUserSwitchInProcess); 2786 } 2787 synchronized (mLockUser) { 2788 if (mUserIdForUserSwitchInProcess != USER_NULL) { 2789 if (mUserIdForUserSwitchInProcess == toUserId) { 2790 if (DBG) { 2791 Slogf.d(TAG, "Ignoring, not legacy"); 2792 } 2793 return; 2794 } 2795 if (DBG) { 2796 Slogf.d(TAG, "Resetting mUserIdForUserSwitchInProcess"); 2797 } 2798 mUserIdForUserSwitchInProcess = USER_NULL; 2799 mRequestIdForUserSwitchInProcess = 0; 2800 } 2801 } 2802 2803 sendUserSwitchUiCallback(toUserId); 2804 2805 // Switch HAL users if user switch is not requested by CarUserService 2806 notifyHalLegacySwitch(fromUserId, toUserId); 2807 } 2808 notifyHalLegacySwitch(@serIdInt int fromUserId, @UserIdInt int toUserId)2809 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) { 2810 if (!isUserHalSupported()) { 2811 if (DBG) { 2812 Slogf.d(TAG, "notifyHalLegacySwitch(): not calling UserHal (not supported)"); 2813 } 2814 return; 2815 } 2816 2817 // switch HAL user 2818 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper, 2819 fromUserId); 2820 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo); 2821 mHal.legacyUserSwitch(request); 2822 } 2823 2824 /** 2825 * Runs the given runnable when user 0 is unlocked. If user 0 is already unlocked, it is 2826 * run inside this call. 2827 * 2828 * @param r Runnable to run. 2829 */ runOnUser0Unlock(@onNull Runnable r)2830 public void runOnUser0Unlock(@NonNull Runnable r) { 2831 Objects.requireNonNull(r, "runnable cannot be null"); 2832 boolean runNow = false; 2833 synchronized (mLockUser) { 2834 if (mUser0Unlocked) { 2835 runNow = true; 2836 } else { 2837 mUser0UnlockTasks.add(r); 2838 } 2839 } 2840 if (runNow) { 2841 r.run(); 2842 } 2843 } 2844 2845 @VisibleForTesting 2846 @NonNull getBackgroundUsersToRestart()2847 ArrayList<Integer> getBackgroundUsersToRestart() { 2848 ArrayList<Integer> backgroundUsersToRestart = null; 2849 synchronized (mLockUser) { 2850 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart); 2851 } 2852 return backgroundUsersToRestart; 2853 } 2854 setSystemUserRestrictions()2855 private void setSystemUserRestrictions() { 2856 // Disable Location service for system user. 2857 LocationManager locationManager = 2858 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 2859 locationManager.setLocationEnabledForUser( 2860 /* enabled= */ false, UserHandle.SYSTEM); 2861 locationManager.setAdasGnssLocationEnabled(false); 2862 } 2863 checkInteractAcrossUsersPermission(String message)2864 private void checkInteractAcrossUsersPermission(String message) { 2865 checkHasAtLeastOnePermissionGranted(mContext, message, 2866 android.Manifest.permission.INTERACT_ACROSS_USERS, 2867 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); 2868 } 2869 2870 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to 2871 // move them to some internal android.os class instead. 2872 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION = 2873 UserManagerHelper.FLAG_MANAGED_PROFILE 2874 | UserManagerHelper.FLAG_PROFILE 2875 | UserManagerHelper.FLAG_EPHEMERAL 2876 | UserManagerHelper.FLAG_RESTRICTED 2877 | UserManagerHelper.FLAG_GUEST 2878 | UserManagerHelper.FLAG_DEMO 2879 | UserManagerHelper.FLAG_FULL; 2880 checkManageUsersPermission(String message)2881 static void checkManageUsersPermission(String message) { 2882 if (!hasManageUsersPermission()) { 2883 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message); 2884 } 2885 } 2886 checkManageOrCreateUsersPermission(String message)2887 private static void checkManageOrCreateUsersPermission(String message) { 2888 if (!hasManageOrCreateUsersPermission()) { 2889 throw new SecurityException( 2890 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: " 2891 + message); 2892 } 2893 } 2894 checkManageOrCreateUsersPermission(int creationFlags)2895 private static void checkManageOrCreateUsersPermission(int creationFlags) { 2896 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) { 2897 if (!hasManageOrCreateUsersPermission()) { 2898 throw new SecurityException("You either need " + MANAGE_USERS + " or " 2899 + CREATE_USERS + "permission to create a user with flags " 2900 + creationFlags); 2901 } 2902 } else if (!hasManageUsersPermission()) { 2903 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user" 2904 + " with flags " + creationFlags); 2905 } 2906 } 2907 hasManageUsersPermission()2908 private static boolean hasManageUsersPermission() { 2909 final int callingUid = Binder.getCallingUid(); 2910 return isSameApp(callingUid, Process.SYSTEM_UID) 2911 || callingUid == Process.ROOT_UID 2912 || hasPermissionGranted(MANAGE_USERS, callingUid); 2913 } 2914 hasManageUsersOrPermission(String alternativePermission)2915 private static boolean hasManageUsersOrPermission(String alternativePermission) { 2916 final int callingUid = Binder.getCallingUid(); 2917 return isSameApp(callingUid, Process.SYSTEM_UID) 2918 || callingUid == Process.ROOT_UID 2919 || hasPermissionGranted(MANAGE_USERS, callingUid) 2920 || hasPermissionGranted(alternativePermission, callingUid); 2921 } 2922 isSameApp(int uid1, int uid2)2923 private static boolean isSameApp(int uid1, int uid2) { 2924 return UserHandle.getAppId(uid1) == UserHandle.getAppId(uid2); 2925 } 2926 hasManageOrCreateUsersPermission()2927 private static boolean hasManageOrCreateUsersPermission() { 2928 return hasManageUsersOrPermission(CREATE_USERS); 2929 } 2930 hasPermissionGranted(String permission, int uid)2931 private static boolean hasPermissionGranted(String permission, int uid) { 2932 return ActivityManagerHelper.checkComponentPermission(permission, uid, /* owningUid= */ -1, 2933 /* exported= */ true) == PackageManager.PERMISSION_GRANTED; 2934 } 2935 userOperationErrorToString(int error)2936 private static String userOperationErrorToString(int error) { 2937 return DebugUtils.constantToString(UserManager.class, "USER_OPERATION_", error); 2938 } 2939 } 2940