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