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