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.MANAGE_USERS; 21 import static android.car.builtin.os.UserManagerHelper.USER_NULL; 22 import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP; 23 24 import static com.android.car.CarServiceUtils.toIntArray; 25 import static com.android.car.PermissionHelper.checkHasAtLeastOnePermissionGranted; 26 import static com.android.car.PermissionHelper.checkHasDumpPermissionGranted; 27 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.DUMP_INFO; 28 29 import android.annotation.IntDef; 30 import android.annotation.NonNull; 31 import android.annotation.Nullable; 32 import android.annotation.UserIdInt; 33 import android.app.ActivityManager; 34 import android.app.admin.DevicePolicyManager; 35 import android.car.Car; 36 import android.car.CarVersion; 37 import android.car.ICarResultReceiver; 38 import android.car.ICarUserService; 39 import android.car.PlatformVersion; 40 import android.car.builtin.app.ActivityManagerHelper; 41 import android.car.builtin.content.pm.PackageManagerHelper; 42 import android.car.builtin.os.TraceHelper; 43 import android.car.builtin.os.UserManagerHelper; 44 import android.car.builtin.util.EventLogHelper; 45 import android.car.builtin.util.Slogf; 46 import android.car.builtin.util.TimingsTraceLog; 47 import android.car.drivingstate.CarUxRestrictions; 48 import android.car.drivingstate.ICarUxRestrictionsChangeListener; 49 import android.car.settings.CarSettings; 50 import android.car.user.CarUserManager; 51 import android.car.user.CarUserManager.UserIdentificationAssociationSetValue; 52 import android.car.user.CarUserManager.UserIdentificationAssociationType; 53 import android.car.user.CarUserManager.UserLifecycleEvent; 54 import android.car.user.CarUserManager.UserLifecycleListener; 55 import android.car.user.UserCreationResult; 56 import android.car.user.UserIdentificationAssociationResponse; 57 import android.car.user.UserLifecycleEventFilter; 58 import android.car.user.UserRemovalResult; 59 import android.car.user.UserStartResult; 60 import android.car.user.UserStopResult; 61 import android.car.user.UserSwitchResult; 62 import android.car.util.concurrent.AndroidFuture; 63 import android.content.Context; 64 import android.content.pm.PackageManager; 65 import android.content.pm.PackageManager.NameNotFoundException; 66 import android.content.res.Resources; 67 import android.hardware.automotive.vehicle.CreateUserRequest; 68 import android.hardware.automotive.vehicle.CreateUserStatus; 69 import android.hardware.automotive.vehicle.InitialUserInfoRequestType; 70 import android.hardware.automotive.vehicle.InitialUserInfoResponseAction; 71 import android.hardware.automotive.vehicle.RemoveUserRequest; 72 import android.hardware.automotive.vehicle.SwitchUserRequest; 73 import android.hardware.automotive.vehicle.SwitchUserStatus; 74 import android.hardware.automotive.vehicle.UserIdentificationGetRequest; 75 import android.hardware.automotive.vehicle.UserIdentificationResponse; 76 import android.hardware.automotive.vehicle.UserIdentificationSetAssociation; 77 import android.hardware.automotive.vehicle.UserIdentificationSetRequest; 78 import android.hardware.automotive.vehicle.UserInfo; 79 import android.hardware.automotive.vehicle.UsersInfo; 80 import android.location.LocationManager; 81 import android.os.Binder; 82 import android.os.Bundle; 83 import android.os.Handler; 84 import android.os.HandlerThread; 85 import android.os.IBinder; 86 import android.os.NewUserRequest; 87 import android.os.NewUserResponse; 88 import android.os.Process; 89 import android.os.RemoteException; 90 import android.os.UserHandle; 91 import android.os.UserManager; 92 import android.provider.Settings; 93 import android.text.TextUtils; 94 import android.util.ArrayMap; 95 import android.util.Log; 96 import android.util.SparseBooleanArray; 97 import android.view.Display; 98 99 import com.android.car.CarLog; 100 import com.android.car.CarServiceBase; 101 import com.android.car.CarServiceUtils; 102 import com.android.car.CarUxRestrictionsManagerService; 103 import com.android.car.R; 104 import com.android.car.hal.HalCallback; 105 import com.android.car.hal.UserHalHelper; 106 import com.android.car.hal.UserHalService; 107 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 108 import com.android.car.internal.ICarServiceHelper; 109 import com.android.car.internal.common.CommonConstants.UserLifecycleEventType; 110 import com.android.car.internal.common.UserHelperLite; 111 import com.android.car.internal.os.CarSystemProperties; 112 import com.android.car.internal.util.ArrayUtils; 113 import com.android.car.internal.util.DebugUtils; 114 import com.android.car.internal.util.FunctionalUtils; 115 import com.android.car.internal.util.IndentingPrintWriter; 116 import com.android.car.pm.CarPackageManagerService; 117 import com.android.car.power.CarPowerManagementService; 118 import com.android.car.user.InitialUserSetter.InitialUserInfo; 119 import com.android.internal.annotations.GuardedBy; 120 import com.android.internal.annotations.VisibleForTesting; 121 import com.android.internal.util.Preconditions; 122 123 import java.io.PrintWriter; 124 import java.lang.annotation.Retention; 125 import java.lang.annotation.RetentionPolicy; 126 import java.util.ArrayList; 127 import java.util.Arrays; 128 import java.util.List; 129 import java.util.Objects; 130 import java.util.concurrent.CountDownLatch; 131 import java.util.concurrent.TimeUnit; 132 133 /** 134 * User service for cars. 135 */ 136 public final class CarUserService extends ICarUserService.Stub implements CarServiceBase { 137 138 @VisibleForTesting 139 static final String TAG = CarLog.tagFor(CarUserService.class); 140 141 private static final boolean DBG = Slogf.isLoggable(TAG, Log.DEBUG); 142 143 /** {@code int} extra used to represent a user id in a {@link ICarResultReceiver} response. */ 144 public static final String BUNDLE_USER_ID = "user.id"; 145 /** {@code int} extra used to represent user flags in a {@link ICarResultReceiver} response. */ 146 public static final String BUNDLE_USER_FLAGS = "user.flags"; 147 /** 148 * {@code String} extra used to represent a user name in a {@link ICarResultReceiver} response. 149 */ 150 public static final String BUNDLE_USER_NAME = "user.name"; 151 /** 152 * {@code int} extra used to represent the user locales in a {@link ICarResultReceiver} 153 * response. 154 */ 155 public static final String BUNDLE_USER_LOCALES = "user.locales"; 156 /** 157 * {@code int} extra used to represent the info action in a {@link ICarResultReceiver} response. 158 */ 159 public static final String BUNDLE_INITIAL_INFO_ACTION = "initial_info.action"; 160 161 public static final String VEHICLE_HAL_NOT_SUPPORTED = "Vehicle Hal not supported."; 162 163 public static final String HANDLER_THREAD_NAME = "UserService"; 164 165 // Constants below must match value of same constants defined by ActivityManager 166 public static final int USER_OP_SUCCESS = 0; 167 public static final int USER_OP_UNKNOWN_USER = -1; 168 public static final int USER_OP_IS_CURRENT = -2; 169 public static final int USER_OP_ERROR_IS_SYSTEM = -3; 170 public static final int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP = -4; 171 172 @VisibleForTesting 173 static final String ERROR_TEMPLATE_NON_ADMIN_CANNOT_CREATE_ADMIN_USERS = 174 "Non-admin user %d can only create non-admin users"; 175 176 @VisibleForTesting 177 static final String ERROR_TEMPLATE_INVALID_USER_TYPE_AND_FLAGS_COMBINATION = 178 "Invalid combination of user type(%s) and flags (%d) for caller with restrictions"; 179 180 @VisibleForTesting 181 static final String ERROR_TEMPLATE_INVALID_FLAGS_FOR_GUEST_CREATION = 182 "Invalid flags %d specified when creating a guest user %s"; 183 184 @VisibleForTesting 185 static final String ERROR_TEMPLATE_DISALLOW_ADD_USER = 186 "Cannot create user because calling user %s has the '%s' restriction"; 187 188 private final Context mContext; 189 private final ActivityManager mAm; 190 private final UserManager mUserManager; 191 private final DevicePolicyManager mDpm; 192 private final int mMaxRunningUsers; 193 private final InitialUserSetter mInitialUserSetter; 194 private final UserPreCreator mUserPreCreator; 195 196 private final Object mLockUser = new Object(); 197 @GuardedBy("mLockUser") 198 private boolean mUser0Unlocked; 199 @GuardedBy("mLockUser") 200 private final ArrayList<Runnable> mUser0UnlockTasks = new ArrayList<>(); 201 /** 202 * Background users that will be restarted in garage mode. This list can include the 203 * current foreground user but the current foreground user should not be restarted. 204 */ 205 @GuardedBy("mLockUser") 206 private final ArrayList<Integer> mBackgroundUsersToRestart = new ArrayList<>(); 207 /** 208 * Keep the list of background users started here. This is wholly for debugging purpose. 209 */ 210 @GuardedBy("mLockUser") 211 private final ArrayList<Integer> mBackgroundUsersRestartedHere = new ArrayList<>(); 212 213 private final UserHalService mHal; 214 215 private final HandlerThread mHandlerThread = CarServiceUtils.getHandlerThread( 216 HANDLER_THREAD_NAME); 217 private final Handler mHandler; 218 219 /** 220 * Internal listeners to be notified on new user activities events. 221 * 222 * <p>This collection should be accessed and manipulated by {@code mHandlerThread} only. 223 */ 224 private final List<InternalLifecycleListener> mUserLifecycleListeners = new ArrayList<>(); 225 226 /** 227 * App listeners to be notified on new user activities events. 228 * 229 * <p>This collection should be accessed and manipulated by {@code mHandlerThread} only. 230 */ 231 private final ArrayMap<IBinder, AppLifecycleListener> mAppLifecycleListeners = 232 new ArrayMap<>(); 233 234 /** 235 * User Id for the user switch in process, if any. 236 */ 237 @GuardedBy("mLockUser") 238 private int mUserIdForUserSwitchInProcess = USER_NULL; 239 /** 240 * Request Id for the user switch in process, if any. 241 */ 242 @GuardedBy("mLockUser") 243 private int mRequestIdForUserSwitchInProcess; 244 private final int mHalTimeoutMs = CarSystemProperties.getUserHalTimeout().orElse(5_000); 245 246 // TODO(b/163566866): Use mSwitchGuestUserBeforeSleep for new create guest request 247 private final boolean mSwitchGuestUserBeforeSleep; 248 249 @Nullable 250 @GuardedBy("mLockUser") 251 private UserHandle mInitialUser; 252 253 private ICarResultReceiver mUserSwitchUiReceiver; 254 255 private final CarUxRestrictionsManagerService mCarUxRestrictionService; 256 257 private final CarPackageManagerService mCarPackageManagerService; 258 259 private static final int PRE_CREATION_STAGE_BEFORE_SUSPEND = 1; 260 261 private static final int PRE_CREATION_STAGE_ON_SYSTEM_START = 2; 262 263 private static final int DEFAULT_PRE_CREATION_DELAY_MS = 0; 264 265 @IntDef(flag = true, prefix = { "PRE_CREATION_STAGE_" }, value = { 266 PRE_CREATION_STAGE_BEFORE_SUSPEND, 267 PRE_CREATION_STAGE_ON_SYSTEM_START, 268 }) 269 @Retention(RetentionPolicy.SOURCE) 270 public @interface PreCreationStage { } 271 272 @PreCreationStage 273 private final int mPreCreationStage; 274 275 private final int mPreCreationDelayMs; 276 277 /** 278 * Whether some operations - like user switch - are restricted by driving safety constraints. 279 */ 280 @GuardedBy("mLockUser") 281 private boolean mUxRestricted; 282 283 /** 284 * If {@code false}, garage mode operations (background users start at garage mode entry and 285 * background users stop at garage mode exit) will be skipped. Controlled using car shell 286 * command {@code adb shell set-start-bg-users-on-garage-mode [true|false]} 287 * Purpose: Garage mode testing and simulation 288 */ 289 @GuardedBy("mLockUser") 290 private boolean mStartBackgroundUsersOnGarageMode = true; 291 292 /** 293 * Callback to notify {@code CarServiceHelper} about driving safety changes (through 294 * {@link ICarServiceHelper#setSafetyMode(boolean). 295 * 296 * <p>NOTE: in theory, that logic should belong to {@code CarDevicePolicyService}, but it's 297 * simpler to do it here (and that service already depends on this one). 298 */ 299 @GuardedBy("mLockUser") 300 private ICarServiceHelper mICarServiceHelper; 301 302 private final ICarUxRestrictionsChangeListener mCarUxRestrictionsChangeListener = 303 new ICarUxRestrictionsChangeListener.Stub() { 304 @Override 305 public void onUxRestrictionsChanged(CarUxRestrictions restrictions) { 306 setUxRestrictions(restrictions); 307 } 308 }; 309 310 /** Map used to avoid calling UserHAL when a user was removed because HAL creation failed. */ 311 @GuardedBy("mLockUser") 312 private final SparseBooleanArray mFailedToCreateUserIds = new SparseBooleanArray(1); 313 314 private final UserHandleHelper mUserHandleHelper; 315 CarUserService(@onNull Context context, @NonNull UserHalService hal, @NonNull UserManager userManager, int maxRunningUsers, @NonNull CarUxRestrictionsManagerService uxRestrictionService, @NonNull CarPackageManagerService carPackageManagerService)316 public CarUserService(@NonNull Context context, @NonNull UserHalService hal, 317 @NonNull UserManager userManager, 318 int maxRunningUsers, 319 @NonNull CarUxRestrictionsManagerService uxRestrictionService, 320 @NonNull CarPackageManagerService carPackageManagerService) { 321 this(context, hal, userManager, new UserHandleHelper(context, userManager), 322 context.getSystemService(DevicePolicyManager.class), 323 context.getSystemService(ActivityManager.class), maxRunningUsers, 324 /* initialUserSetter= */ null, /* userPreCreator= */ null, uxRestrictionService, 325 null, carPackageManagerService); 326 } 327 328 @VisibleForTesting CarUserService(@onNull Context context, @NonNull UserHalService hal, @NonNull UserManager userManager, @NonNull UserHandleHelper userHandleHelper, @NonNull DevicePolicyManager dpm, @NonNull ActivityManager am, int maxRunningUsers, @Nullable InitialUserSetter initialUserSetter, @Nullable UserPreCreator userPreCreator, @NonNull CarUxRestrictionsManagerService uxRestrictionService, @Nullable Handler handler, @NonNull CarPackageManagerService carPackageManagerService)329 CarUserService(@NonNull Context context, @NonNull UserHalService hal, 330 @NonNull UserManager userManager, 331 @NonNull UserHandleHelper userHandleHelper, 332 @NonNull DevicePolicyManager dpm, 333 @NonNull ActivityManager am, 334 int maxRunningUsers, 335 @Nullable InitialUserSetter initialUserSetter, 336 @Nullable UserPreCreator userPreCreator, 337 @NonNull CarUxRestrictionsManagerService uxRestrictionService, 338 @Nullable Handler handler, 339 @NonNull CarPackageManagerService carPackageManagerService) { 340 Slogf.d(TAG, "CarUserService(): DBG=%b, user=%s", DBG, context.getUser()); 341 mContext = context; 342 mHal = hal; 343 mAm = am; 344 mMaxRunningUsers = maxRunningUsers; 345 mUserManager = userManager; 346 mDpm = dpm; 347 mUserHandleHelper = userHandleHelper; 348 mHandler = handler == null ? new Handler(mHandlerThread.getLooper()) : handler; 349 mInitialUserSetter = 350 initialUserSetter == null ? new InitialUserSetter(context, this, 351 (u) -> setInitialUser(u), mUserHandleHelper) : initialUserSetter; 352 mUserPreCreator = 353 userPreCreator == null ? new UserPreCreator(context, mUserManager) : userPreCreator; 354 Resources resources = context.getResources(); 355 mSwitchGuestUserBeforeSleep = resources.getBoolean( 356 R.bool.config_switchGuestUserBeforeGoingSleep); 357 mCarUxRestrictionService = uxRestrictionService; 358 mCarPackageManagerService = carPackageManagerService; 359 mPreCreationStage = resources.getInteger(R.integer.config_userPreCreationStage); 360 int preCreationDelayMs = resources 361 .getInteger(R.integer.config_userPreCreationDelay); 362 mPreCreationDelayMs = preCreationDelayMs < DEFAULT_PRE_CREATION_DELAY_MS 363 ? DEFAULT_PRE_CREATION_DELAY_MS 364 : preCreationDelayMs; 365 } 366 367 @Override 368 public void init() { 369 if (DBG) { 370 Slogf.d(TAG, "init()"); 371 } 372 373 mCarUxRestrictionService.registerUxRestrictionsChangeListener( 374 mCarUxRestrictionsChangeListener, Display.DEFAULT_DISPLAY); 375 376 setUxRestrictions(mCarUxRestrictionService.getCurrentUxRestrictions()); 377 } 378 379 @Override 380 public void release() { 381 if (DBG) { 382 Slogf.d(TAG, "release()"); 383 } 384 385 mCarUxRestrictionService 386 .unregisterUxRestrictionsChangeListener(mCarUxRestrictionsChangeListener); 387 } 388 389 @Override 390 @ExcludeFromCodeCoverageGeneratedReport(reason = DUMP_INFO) 391 public void dump(@NonNull IndentingPrintWriter writer) { 392 checkHasDumpPermissionGranted(mContext, "dump()"); 393 394 writer.println("*CarUserService*"); 395 writer.printf("DBG=%b\n", DBG); 396 handleDumpListeners(writer); 397 writer.printf("User switch UI receiver %s\n", mUserSwitchUiReceiver); 398 synchronized (mLockUser) { 399 writer.println("User0Unlocked: " + mUser0Unlocked); 400 writer.println("BackgroundUsersToRestart: " + mBackgroundUsersToRestart); 401 writer.println("BackgroundUsersRestarted: " + mBackgroundUsersRestartedHere); 402 if (mFailedToCreateUserIds.size() > 0) { 403 writer.println("FailedToCreateUserIds: " + mFailedToCreateUserIds); 404 } 405 writer.printf("Is UX restricted: %b\n", mUxRestricted); 406 writer.printf("Start Background Users On Garage Mode=%s\n", 407 mStartBackgroundUsersOnGarageMode); 408 writer.printf("Initial user: %s\n", mInitialUser); 409 } 410 411 writer.println("SwitchGuestUserBeforeSleep: " + mSwitchGuestUserBeforeSleep); 412 writer.printf("PreCreateUserStages: %s\n", preCreationStageToString(mPreCreationStage)); 413 writer.printf("PreCreationDelayMs: %s\n", mPreCreationDelayMs); 414 415 writer.println("MaxRunningUsers: " + mMaxRunningUsers); 416 writer.printf("User HAL: supported=%b, timeout=%dms\n", isUserHalSupported(), 417 mHalTimeoutMs); 418 419 writer.println("Relevant overlayable properties"); 420 Resources res = mContext.getResources(); writer.increaseIndent()421 writer.increaseIndent(); 422 writer.printf("owner_name=%s\n", UserManagerHelper.getDefaultUserName(mContext)); 423 writer.printf("default_guest_name=%s\n", res.getString(R.string.default_guest_name)); 424 writer.printf("config_multiuserMaxRunningUsers=%d\n", 425 UserManagerHelper.getMaxRunningUsers(mContext)); writer.decreaseIndent()426 writer.decreaseIndent(); 427 writer.printf("User switch in process=%d\n", mUserIdForUserSwitchInProcess); 428 writer.printf("Request Id for the user switch in process=%d\n ", 429 mRequestIdForUserSwitchInProcess); 430 writer.printf("System UI package name=%s\n", 431 PackageManagerHelper.getSystemUiPackageName(mContext)); 432 433 writer.println("Relevant Global settings"); writer.increaseIndent()434 writer.increaseIndent(); dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_USER_ID)435 dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_USER_ID); dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID)436 dumpGlobalProperty(writer, CarSettings.Global.LAST_ACTIVE_PERSISTENT_USER_ID); writer.decreaseIndent()437 writer.decreaseIndent(); 438 mInitialUserSetter.dump(writer)439 mInitialUserSetter.dump(writer); 440 } 441 preCreationStageToString(@reCreationStage int stage)442 private static String preCreationStageToString(@PreCreationStage int stage) { 443 return DebugUtils.flagsToString(CarUserService.class, "PRE_CREATION_STAGE_", stage); 444 } 445 dumpGlobalProperty(IndentingPrintWriter writer, String property)446 private void dumpGlobalProperty(IndentingPrintWriter writer, String property) { 447 String value = Settings.Global.getString(mContext.getContentResolver(), property); 448 writer.printf("%s=%s\n", property, value); 449 } 450 handleDumpListeners(IndentingPrintWriter writer)451 private void handleDumpListeners(IndentingPrintWriter writer) { 452 writer.increaseIndent(); 453 CountDownLatch latch = new CountDownLatch(1); 454 mHandler.post(() -> { 455 handleDumpServiceLifecycleListeners(writer); 456 handleDumpAppLifecycleListeners(writer); 457 latch.countDown(); 458 }); 459 int timeout = 5; 460 try { 461 if (!latch.await(timeout, TimeUnit.SECONDS)) { 462 writer.printf("Handler thread didn't respond in %ds when dumping listeners\n", 463 timeout); 464 } 465 } catch (InterruptedException e) { 466 Thread.currentThread().interrupt(); 467 writer.println("Interrupted waiting for handler thread to dump app and user listeners"); 468 } 469 writer.decreaseIndent(); 470 } 471 handleDumpServiceLifecycleListeners(PrintWriter writer)472 private void handleDumpServiceLifecycleListeners(PrintWriter writer) { 473 if (mUserLifecycleListeners.isEmpty()) { 474 writer.println("No lifecycle listeners for internal services"); 475 return; 476 } 477 int size = mUserLifecycleListeners.size(); 478 writer.printf("%d lifecycle listener%s for services\n", size, size == 1 ? "" : "s"); 479 String indent = " "; 480 for (int i = 0; i < size; i++) { 481 InternalLifecycleListener listener = mUserLifecycleListeners.get(i); 482 writer.printf("%slistener=%s, filter=%s\n", indent, 483 FunctionalUtils.getLambdaName(listener.listener), listener.filter); 484 } 485 } 486 handleDumpAppLifecycleListeners(IndentingPrintWriter writer)487 private void handleDumpAppLifecycleListeners(IndentingPrintWriter writer) { 488 int size = mAppLifecycleListeners.size(); 489 if (size == 0) { 490 writer.println("No lifecycle listeners for apps"); 491 return; 492 } 493 writer.printf("%d lifecycle listener%s for apps\n", size, size == 1 ? "" : "s"); 494 writer.increaseIndent(); 495 for (int i = 0; i < size; i++) { 496 mAppLifecycleListeners.valueAt(i).dump(writer); 497 } 498 writer.decreaseIndent(); 499 } 500 501 @Override setLifecycleListenerForApp(String packageName, UserLifecycleEventFilter filter, ICarResultReceiver receiver)502 public void setLifecycleListenerForApp(String packageName, UserLifecycleEventFilter filter, 503 ICarResultReceiver receiver) { 504 int uid = Binder.getCallingUid(); 505 EventLogHelper.writeCarUserServiceSetLifecycleListener(uid, packageName); 506 checkInteractAcrossUsersPermission("setLifecycleListenerForApp-" + uid + "-" + packageName); 507 508 IBinder receiverBinder = receiver.asBinder(); 509 mHandler.post(() -> { 510 AppLifecycleListener listener = mAppLifecycleListeners.get(receiverBinder); 511 if (listener == null) { 512 listener = new AppLifecycleListener(uid, packageName, receiver, filter, 513 (l) -> onListenerDeath(l)); 514 Slogf.d(TAG, "Adding %s (using binder %s) with filter %s", 515 listener, receiverBinder, filter); 516 mAppLifecycleListeners.put(receiverBinder, listener); 517 } else { 518 // Same listener already exists. Only add the additional filter. 519 Slogf.d(TAG, "Adding filter %s to the listener %s (for binder %s)", filter, 520 listener, receiverBinder); 521 listener.addFilter(filter); 522 } 523 }); 524 } 525 onListenerDeath(AppLifecycleListener listener)526 private void onListenerDeath(AppLifecycleListener listener) { 527 Slogf.i(TAG, "Removing listener %s on binder death", listener); 528 mHandler.post(() -> mAppLifecycleListeners.remove(listener.receiver.asBinder())); 529 } 530 531 @Override resetLifecycleListenerForApp(ICarResultReceiver receiver)532 public void resetLifecycleListenerForApp(ICarResultReceiver receiver) { 533 int uid = Binder.getCallingUid(); 534 checkInteractAcrossUsersPermission("resetLifecycleListenerForApp-" + uid); 535 IBinder receiverBinder = receiver.asBinder(); 536 mHandler.post(() -> { 537 AppLifecycleListener listener = mAppLifecycleListeners.get(receiverBinder); 538 if (listener == null) { 539 Slogf.e(TAG, "resetLifecycleListenerForApp(uid=%d): no listener for receiver", uid); 540 return; 541 } 542 if (listener.uid != uid) { 543 Slogf.e(TAG, "resetLifecycleListenerForApp(): uid mismatch (called by %d) for " 544 + "listener %s", uid, listener); 545 } 546 EventLogHelper.writeCarUserServiceResetLifecycleListener(uid, 547 listener.packageName); 548 if (DBG) { 549 Slogf.d(TAG, "Removing %s (using binder %s)", listener, receiverBinder); 550 } 551 mAppLifecycleListeners.remove(receiverBinder); 552 553 listener.onDestroy(); 554 }); 555 } 556 557 /** 558 * Gets the initial foreground user after the device boots or resumes from suspension. 559 * 560 * <p>When the OEM supports the User HAL, the initial user won't be available until the HAL 561 * returns the initial value to {@code CarService} - if HAL takes too long or times out, this 562 * method returns {@code null}. 563 * 564 * <p>If the HAL eventually times out, {@code CarService} will fallback to its default behavior 565 * (like switching to the last active user), and this method will return the result of such 566 * operation. 567 * 568 * <p>Notice that if {@code CarService} crashes, subsequent calls to this method will return 569 * {@code null}. 570 * 571 * @hide 572 */ 573 @Nullable getInitialUser()574 public UserHandle getInitialUser() { 575 checkInteractAcrossUsersPermission("getInitialUser"); 576 synchronized (mLockUser) { 577 return mInitialUser; 578 } 579 } 580 581 /** 582 * Sets the initial foreground user after the device boots or resumes from suspension. 583 */ setInitialUser(@ullable UserHandle user)584 public void setInitialUser(@Nullable UserHandle user) { 585 EventLogHelper 586 .writeCarUserServiceSetInitialUser(user == null ? USER_NULL : user.getIdentifier()); 587 synchronized (mLockUser) { 588 mInitialUser = user; 589 } 590 if (user == null) { 591 // This mean InitialUserSetter failed and could not fallback, so the initial user was 592 // not switched (and most likely is SYSTEM_USER). 593 // TODO(b/153104378): should we set it to ActivityManager.getCurrentUser() instead? 594 Slogf.wtf(TAG, "Initial user set to null"); 595 return; 596 } 597 sendInitialUserToSystemServer(user); 598 } 599 600 /** 601 * Sets the initial foreground user after car service is crashed and reconnected. 602 */ setInitialUserFromSystemServer(@ullable UserHandle user)603 public void setInitialUserFromSystemServer(@Nullable UserHandle user) { 604 if (user == null || user.getIdentifier() == USER_NULL) { 605 Slogf.e(TAG, 606 "setInitialUserFromSystemServer: Not setting initial user as user is NULL "); 607 return; 608 } 609 610 if (DBG) { 611 Slogf.d(TAG, "setInitialUserFromSystemServer: initial User: %s", user); 612 } 613 614 synchronized (mLockUser) { 615 mInitialUser = user; 616 } 617 } 618 sendInitialUserToSystemServer(UserHandle user)619 private void sendInitialUserToSystemServer(UserHandle user) { 620 ICarServiceHelper iCarServiceHelper; 621 synchronized (mLockUser) { 622 iCarServiceHelper = mICarServiceHelper; 623 } 624 625 if (iCarServiceHelper == null) { 626 Slogf.e(TAG, "sendInitialUserToSystemServer(%s): CarServiceHelper is NULL.", user); 627 return; 628 } 629 630 try { 631 iCarServiceHelper.sendInitialUser(user); 632 } catch (RemoteException e) { 633 Slogf.e(TAG, e, "Error calling sendInitialUser(%s)", user); 634 } 635 } 636 initResumeReplaceGuest()637 private void initResumeReplaceGuest() { 638 int currentUserId = ActivityManager.getCurrentUser(); 639 UserHandle currentUser = mUserHandleHelper.getExistingUserHandle(currentUserId); 640 641 if (currentUser == null) { 642 Slogf.wtf(TAG, "Current user (%d) doesn't exist", currentUserId); 643 } 644 645 if (!mInitialUserSetter.canReplaceGuestUser(currentUser)) return; // Not a guest 646 647 InitialUserInfo info = 648 new InitialUserSetter.Builder(InitialUserSetter.TYPE_REPLACE_GUEST).build(); 649 650 mInitialUserSetter.set(info); 651 } 652 653 /** 654 * Calls to switch user at the power suspend. 655 * 656 * <p><b>Note:</b> Should be used only by {@link CarPowerManagementService} 657 * 658 */ onSuspend()659 public void onSuspend() { 660 if (DBG) { 661 Slogf.d(TAG, "onSuspend called."); 662 } 663 664 if (mSwitchGuestUserBeforeSleep) { 665 initResumeReplaceGuest(); 666 } 667 668 if ((mPreCreationStage & PRE_CREATION_STAGE_BEFORE_SUSPEND) != 0) { 669 preCreateUsersInternal(/* waitTimeMs= */ DEFAULT_PRE_CREATION_DELAY_MS); 670 } 671 } 672 673 /** 674 * Calls to switch user at the power resume. 675 * 676 * <p> 677 * <b>Note:</b> Should be used only by {@link CarPowerManagementService} 678 * 679 */ onResume()680 public void onResume() { 681 if (DBG) { 682 Slogf.d(TAG, "onResume called."); 683 } 684 685 mHandler.post(() -> initBootUser(InitialUserInfoRequestType.RESUME)); 686 } 687 688 /** 689 * Calls to start user at the android startup. 690 */ initBootUser()691 public void initBootUser() { 692 mHandler.post(() -> initBootUser(getInitialUserInfoRequestType())); 693 694 if ((mPreCreationStage & PRE_CREATION_STAGE_ON_SYSTEM_START) != 0) { 695 preCreateUsersInternal(mPreCreationDelayMs); 696 } 697 } 698 initBootUser(int requestType)699 private void initBootUser(int requestType) { 700 boolean replaceGuest = 701 requestType == InitialUserInfoRequestType.RESUME && !mSwitchGuestUserBeforeSleep; 702 checkManageUsersPermission("startInitialUser"); 703 704 if (!isUserHalSupported()) { 705 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest, 706 /* supportsOverrideUserIdProperty= */ true); 707 EventLogHelper.writeCarUserServiceInitialUserInfoReqComplete(requestType); 708 return; 709 } 710 711 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 712 EventLogHelper.writeCarUserServiceInitialUserInfoReq(requestType, 713 mHalTimeoutMs, usersInfo.currentUser.userId, usersInfo.currentUser.flags, 714 usersInfo.numberUsers); 715 716 mHal.getInitialUserInfo(requestType, mHalTimeoutMs, usersInfo, (status, resp) -> { 717 if (resp != null) { 718 EventLogHelper.writeCarUserServiceInitialUserInfoResp( 719 status, resp.action, resp.userToSwitchOrCreate.userId, 720 resp.userToSwitchOrCreate.flags, resp.userNameToCreate, resp.userLocales); 721 722 String userLocales = resp.userLocales; 723 InitialUserInfo info; 724 switch(resp.action) { 725 case InitialUserInfoResponseAction.SWITCH: 726 int userId = resp.userToSwitchOrCreate.userId; 727 if (userId <= 0) { 728 Slogf.w(TAG, "invalid (or missing) user id sent by HAL: %d", userId); 729 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest, 730 /* supportsOverrideUserIdProperty= */ false); 731 break; 732 } 733 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_SWITCH) 734 .setUserLocales(userLocales) 735 .setSwitchUserId(userId) 736 .setReplaceGuest(replaceGuest) 737 .build(); 738 mInitialUserSetter.set(info); 739 break; 740 741 case InitialUserInfoResponseAction.CREATE: 742 int halFlags = resp.userToSwitchOrCreate.flags; 743 String userName = resp.userNameToCreate; 744 info = new InitialUserSetter.Builder(InitialUserSetter.TYPE_CREATE) 745 .setUserLocales(userLocales) 746 .setNewUserName(userName) 747 .setNewUserFlags(halFlags) 748 .build(); 749 mInitialUserSetter.set(info); 750 break; 751 752 case InitialUserInfoResponseAction.DEFAULT: 753 fallbackToDefaultInitialUserBehavior(userLocales, replaceGuest, 754 /* supportsOverrideUserIdProperty= */ false); 755 break; 756 default: 757 Slogf.w(TAG, "invalid response action on %s", resp); 758 fallbackToDefaultInitialUserBehavior(/* userLocales= */ null, replaceGuest, 759 /* supportsOverrideUserIdProperty= */ false); 760 break; 761 762 } 763 } else { 764 EventLogHelper.writeCarUserServiceInitialUserInfoResp(status, /* action= */ 0, 765 /* userId= */ 0, /* flags= */ 0, 766 /* safeName= */ "", /* userLocales= */ ""); 767 fallbackToDefaultInitialUserBehavior(/* user locale */ null, replaceGuest, 768 /* supportsOverrideUserIdProperty= */ false); 769 } 770 EventLogHelper.writeCarUserServiceInitialUserInfoReqComplete(requestType); 771 }); 772 } 773 fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest, boolean supportsOverrideUserIdProperty)774 private void fallbackToDefaultInitialUserBehavior(String userLocales, boolean replaceGuest, 775 boolean supportsOverrideUserIdProperty) { 776 InitialUserInfo info = new InitialUserSetter.Builder( 777 InitialUserSetter.TYPE_DEFAULT_BEHAVIOR) 778 .setUserLocales(userLocales) 779 .setReplaceGuest(replaceGuest) 780 .setSupportsOverrideUserIdProperty(supportsOverrideUserIdProperty) 781 .build(); 782 mInitialUserSetter.set(info); 783 } 784 785 @VisibleForTesting getInitialUserInfoRequestType()786 int getInitialUserInfoRequestType() { 787 if (!mInitialUserSetter.hasInitialUser()) { 788 return InitialUserInfoRequestType.FIRST_BOOT; 789 } 790 if (mContext.getPackageManager().isDeviceUpgrading()) { 791 return InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA; 792 } 793 return InitialUserInfoRequestType.COLD_BOOT; 794 } 795 796 /** 797 * Sets the {@link ICarServiceHelper} so it can receive UX restriction updates. 798 */ setCarServiceHelper(ICarServiceHelper helper)799 public void setCarServiceHelper(ICarServiceHelper helper) { 800 boolean restricted; 801 synchronized (mLockUser) { 802 mICarServiceHelper = helper; 803 restricted = mUxRestricted; 804 } 805 updateSafetyMode(helper, restricted); 806 } 807 updateSafetyMode(@ullable ICarServiceHelper helper, boolean restricted)808 private void updateSafetyMode(@Nullable ICarServiceHelper helper, boolean restricted) { 809 if (helper == null) return; 810 811 boolean isSafe = !restricted; 812 try { 813 helper.setSafetyMode(isSafe); 814 } catch (Exception e) { 815 Slogf.e(TAG, e, "Exception calling helper.setDpmSafetyMode(%b)", isSafe); 816 } 817 } 818 setUxRestrictions(@ullable CarUxRestrictions restrictions)819 private void setUxRestrictions(@Nullable CarUxRestrictions restrictions) { 820 boolean restricted = restrictions != null 821 && (restrictions.getActiveRestrictions() & UX_RESTRICTIONS_NO_SETUP) 822 == UX_RESTRICTIONS_NO_SETUP; 823 if (DBG) { 824 Slogf.d(TAG, "setUxRestrictions(%s): restricted=%b", restrictions, restricted); 825 } else { 826 Slogf.i(TAG, "Setting UX restricted to %b", restricted); 827 } 828 829 ICarServiceHelper helper = null; 830 831 synchronized (mLockUser) { 832 mUxRestricted = restricted; 833 if (mICarServiceHelper == null) { 834 Slogf.e(TAG, "onUxRestrictionsChanged(): no mICarServiceHelper"); 835 } 836 helper = mICarServiceHelper; 837 } 838 updateSafetyMode(helper, restricted); 839 } 840 isUxRestricted()841 private boolean isUxRestricted() { 842 synchronized (mLockUser) { 843 return mUxRestricted; 844 } 845 } 846 847 /** 848 * Calls the {@link UserHalService} and {@link ActivityManager} for user switch. 849 * 850 * <p> 851 * When everything works well, the workflow is: 852 * <ol> 853 * <li> {@link UserHalService} is called for HAL user switch with ANDROID_SWITCH request 854 * type, current user id, target user id, and a callback. 855 * <li> HAL called back with SUCCESS. 856 * <li> {@link ActivityManager} is called for Android user switch. 857 * <li> Receiver would receive {@code STATUS_SUCCESSFUL}. 858 * <li> Once user is unlocked, {@link UserHalService} is again called with ANDROID_POST_SWITCH 859 * request type, current user id, and target user id. In this case, the current and target 860 * user IDs would be same. 861 * <ol/> 862 * 863 * <p> 864 * Corner cases: 865 * <ul> 866 * <li> If target user is already the current user, no user switch is performed and receiver 867 * would receive {@code STATUS_OK_USER_ALREADY_IN_FOREGROUND} right away. 868 * <li> If HAL user switch call fails, no Android user switch. Receiver would receive 869 * {@code STATUS_HAL_INTERNAL_FAILURE}. 870 * <li> If HAL user switch call is successful, but android user switch call fails, 871 * {@link UserHalService} is again called with request type POST_SWITCH, current user id, and 872 * target user id, but in this case the current and target user IDs would be different. 873 * <li> If another user switch request for the same target user is received while previous 874 * request is in process, receiver would receive 875 * {@code STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO} for the new request right away. 876 * <li> If a user switch request is received while another user switch request for different 877 * target user is in process, the previous request would be abandoned and new request will be 878 * processed. No POST_SWITCH would be sent for the previous request. 879 * <ul/> 880 * 881 * @param targetUserId - target user Id 882 * @param timeoutMs - timeout for HAL to wait 883 * @param receiver - receiver for the results 884 */ 885 @Override switchUser(@serIdInt int targetUserId, int timeoutMs, @NonNull AndroidFuture<UserSwitchResult> receiver)886 public void switchUser(@UserIdInt int targetUserId, int timeoutMs, 887 @NonNull AndroidFuture<UserSwitchResult> receiver) { 888 EventLogHelper.writeCarUserServiceSwitchUserReq(targetUserId, timeoutMs); 889 checkManageOrCreateUsersPermission("switchUser"); 890 Objects.requireNonNull(receiver); 891 UserHandle targetUser = mUserHandleHelper.getExistingUserHandle(targetUserId); 892 Preconditions.checkArgument(targetUser != null, "Target user doesn't exist"); 893 if (mUserManager.getUserSwitchability() != UserManager.SWITCHABILITY_STATUS_OK) { 894 sendUserSwitchResult(receiver, /* isLogout= */ false, 895 UserSwitchResult.STATUS_NOT_SWITCHABLE); 896 return; 897 } 898 mHandler.post(() -> handleSwitchUser(targetUser, timeoutMs, receiver, 899 /* isLogout= */ false)); 900 } 901 902 @Override logoutUser(int timeoutMs, @NonNull AndroidFuture<UserSwitchResult> receiver)903 public void logoutUser(int timeoutMs, @NonNull AndroidFuture<UserSwitchResult> receiver) { 904 checkManageOrCreateUsersPermission("logoutUser"); 905 Objects.requireNonNull(receiver); 906 907 UserHandle targetUser = mDpm.getLogoutUser(); 908 int logoutUserId = targetUser == null ? UserManagerHelper.USER_NULL 909 : targetUser.getIdentifier(); 910 EventLogHelper.writeCarUserServiceLogoutUserReq(logoutUserId, timeoutMs); 911 912 if (targetUser == null) { 913 Slogf.w(TAG, "logoutUser() called when current user is not logged in"); 914 sendUserSwitchResult(receiver, /* isLogout= */ true, 915 UserSwitchResult.STATUS_NOT_LOGGED_IN); 916 return; 917 } 918 919 mHandler.post(() -> handleSwitchUser(targetUser, timeoutMs, receiver, 920 /* isLogout= */ true)); 921 } 922 handleSwitchUser(@onNull UserHandle targetUser, int timeoutMs, @NonNull AndroidFuture<UserSwitchResult> receiver, boolean isLogout)923 private void handleSwitchUser(@NonNull UserHandle targetUser, int timeoutMs, 924 @NonNull AndroidFuture<UserSwitchResult> receiver, boolean isLogout) { 925 int currentUser = ActivityManager.getCurrentUser(); 926 int targetUserId = targetUser.getIdentifier(); 927 if (currentUser == targetUserId) { 928 if (DBG) { 929 Slogf.d(TAG, "Current user is same as requested target user: %d", targetUserId); 930 } 931 int resultStatus = UserSwitchResult.STATUS_OK_USER_ALREADY_IN_FOREGROUND; 932 sendUserSwitchResult(receiver, isLogout, resultStatus); 933 return; 934 } 935 936 if (isUxRestricted()) { 937 sendUserSwitchResult(receiver, isLogout, 938 UserSwitchResult.STATUS_UX_RESTRICTION_FAILURE); 939 return; 940 } 941 942 // If User Hal is not supported, just android user switch. 943 if (!isUserHalSupported()) { 944 int result = switchOrLogoutUser(targetUser, isLogout); 945 if (result == UserManager.USER_OPERATION_SUCCESS) { 946 sendUserSwitchResult(receiver, isLogout, UserSwitchResult.STATUS_SUCCESSFUL); 947 return; 948 } 949 sendUserSwitchResult(receiver, isLogout, HalCallback.STATUS_INVALID, 950 UserSwitchResult.STATUS_ANDROID_FAILURE, result, /* errorMessage= */ null); 951 return; 952 } 953 954 synchronized (mLockUser) { 955 if (DBG) { 956 Slogf.d(TAG, "handleSwitchUser(%d): currentuser=%s, isLogout=%b, " 957 + "mUserIdForUserSwitchInProcess=%b", targetUserId, currentUser, isLogout, 958 mUserIdForUserSwitchInProcess); 959 } 960 961 // If there is another request for the same target user, return another request in 962 // process, else {@link mUserIdForUserSwitchInProcess} is updated and {@link 963 // mRequestIdForUserSwitchInProcess} is reset. It is possible that there may be another 964 // user switch request in process for different target user, but that request is now 965 // ignored. 966 if (mUserIdForUserSwitchInProcess == targetUserId) { 967 Slogf.w(TAG, "switchUser(%s): another user switch request (id=%d) in process for " 968 + "that user", targetUser, mRequestIdForUserSwitchInProcess); 969 int resultStatus = UserSwitchResult.STATUS_TARGET_USER_ALREADY_BEING_SWITCHED_TO; 970 sendUserSwitchResult(receiver, isLogout, resultStatus); 971 return; 972 } else { 973 if (DBG) { 974 Slogf.d(TAG, "Changing mUserIdForUserSwitchInProcess from %d to %d", 975 mUserIdForUserSwitchInProcess, targetUserId); 976 } 977 mUserIdForUserSwitchInProcess = targetUserId; 978 mRequestIdForUserSwitchInProcess = 0; 979 } 980 } 981 982 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 983 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo); 984 985 if (DBG) { 986 Slogf.d(TAG, "calling mHal.switchUser(%s)", request); 987 } 988 mHal.switchUser(request, timeoutMs, (halCallbackStatus, resp) -> { 989 if (DBG) { 990 Slogf.d(TAG, "switch response: status=%s, resp=%s", 991 Integer.toString(halCallbackStatus), resp); 992 } 993 994 int resultStatus = UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE; 995 Integer androidFailureStatus = null; 996 997 synchronized (mLockUser) { 998 if (halCallbackStatus != HalCallback.STATUS_OK || resp == null) { 999 Slogf.w(TAG, "invalid callback status (%s) or null response (%s)", 1000 Integer.toString(halCallbackStatus), resp); 1001 sendUserSwitchResult(receiver, isLogout, resultStatus); 1002 mUserIdForUserSwitchInProcess = USER_NULL; 1003 return; 1004 } 1005 1006 if (mUserIdForUserSwitchInProcess != targetUserId) { 1007 // Another user switch request received while HAL responded. No need to 1008 // process this request further 1009 Slogf.w(TAG, "Another user switch received while HAL responsed. Request" 1010 + " abandoned for user %d. Current user in process: %d", targetUserId, 1011 mUserIdForUserSwitchInProcess); 1012 resultStatus = 1013 UserSwitchResult.STATUS_TARGET_USER_ABANDONED_DUE_TO_A_NEW_REQUEST; 1014 sendUserSwitchResult(receiver, isLogout, resultStatus); 1015 mUserIdForUserSwitchInProcess = USER_NULL; 1016 return; 1017 } 1018 1019 switch (resp.status) { 1020 case SwitchUserStatus.SUCCESS: 1021 int result = switchOrLogoutUser(targetUser, isLogout); 1022 if (result == UserManager.USER_OPERATION_SUCCESS) { 1023 sendUserSwitchUiCallback(targetUserId); 1024 resultStatus = UserSwitchResult.STATUS_SUCCESSFUL; 1025 mRequestIdForUserSwitchInProcess = resp.requestId; 1026 } else { 1027 resultStatus = UserSwitchResult.STATUS_ANDROID_FAILURE; 1028 if (isLogout) { 1029 // Send internal result (there's no point on sending for regular 1030 // switch as it will always be UNKNOWN_ERROR 1031 androidFailureStatus = result; 1032 } 1033 postSwitchHalResponse(resp.requestId, targetUserId); 1034 } 1035 break; 1036 case SwitchUserStatus.FAILURE: 1037 // HAL failed to switch user 1038 resultStatus = UserSwitchResult.STATUS_HAL_FAILURE; 1039 break; 1040 default: 1041 // Shouldn't happen because UserHalService validates the status 1042 Slogf.wtf(TAG, "Received invalid user switch status from HAL: %s", resp); 1043 } 1044 1045 if (mRequestIdForUserSwitchInProcess == 0) { 1046 mUserIdForUserSwitchInProcess = USER_NULL; 1047 } 1048 } 1049 sendUserSwitchResult(receiver, isLogout, halCallbackStatus, resultStatus, 1050 androidFailureStatus, resp.errorMessage); 1051 }); 1052 } 1053 switchOrLogoutUser(UserHandle targetUser, boolean isLogout)1054 private int switchOrLogoutUser(UserHandle targetUser, boolean isLogout) { 1055 if (isLogout) { 1056 int result = mDpm.logoutUser(); 1057 if (result != UserManager.USER_OPERATION_SUCCESS) { 1058 Slogf.w(TAG, "failed to logout to user %s using DPM: result=%s", targetUser, 1059 userOperationErrorToString(result)); 1060 } 1061 return result; 1062 } 1063 1064 if (!mAm.switchUser(targetUser)) { 1065 Slogf.w(TAG, "failed to switch to user %s using AM", targetUser); 1066 return UserManager.USER_OPERATION_ERROR_UNKNOWN; 1067 } 1068 1069 return UserManager.USER_OPERATION_SUCCESS; 1070 } 1071 1072 @Override removeUser(@serIdInt int userId, AndroidFuture<UserRemovalResult> receiver)1073 public void removeUser(@UserIdInt int userId, AndroidFuture<UserRemovalResult> receiver) { 1074 removeUser(userId, /* hasCallerRestrictions= */ false, receiver); 1075 } 1076 1077 /** 1078 * Internal implementation of {@code removeUser()}, which is used by both 1079 * {@code ICarUserService} and {@code ICarDevicePolicyService}. 1080 * 1081 * @param userId user to be removed 1082 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can 1083 * only remove itself. 1084 * @param receiver to post results 1085 */ removeUser(@serIdInt int userId, boolean hasCallerRestrictions, AndroidFuture<UserRemovalResult> receiver)1086 public void removeUser(@UserIdInt int userId, boolean hasCallerRestrictions, 1087 AndroidFuture<UserRemovalResult> receiver) { 1088 checkManageOrCreateUsersPermission("removeUser"); 1089 EventLogHelper.writeCarUserServiceRemoveUserReq(userId, 1090 hasCallerRestrictions ? 1 : 0); 1091 1092 if (hasCallerRestrictions) { 1093 // Restrictions: non-admin user can only remove itself, admins have no restrictions 1094 int callingUserId = Binder.getCallingUserHandle().getIdentifier(); 1095 if (!mUserHandleHelper.isAdminUser(UserHandle.of(callingUserId)) 1096 && userId != callingUserId) { 1097 throw new SecurityException("Non-admin user " + callingUserId 1098 + " can only remove itself"); 1099 } 1100 } 1101 mHandler.post(() -> handleRemoveUser(userId, hasCallerRestrictions, receiver)); 1102 } 1103 handleRemoveUser(@serIdInt int userId, boolean hasCallerRestrictions, AndroidFuture<UserRemovalResult> receiver)1104 private void handleRemoveUser(@UserIdInt int userId, boolean hasCallerRestrictions, 1105 AndroidFuture<UserRemovalResult> receiver) { 1106 UserHandle user = mUserHandleHelper.getExistingUserHandle(userId); 1107 if (user == null) { 1108 sendUserRemovalResult(userId, UserRemovalResult.STATUS_USER_DOES_NOT_EXIST, receiver); 1109 return; 1110 } 1111 UserInfo halUser = new UserInfo(); 1112 halUser.userId = user.getIdentifier(); 1113 halUser.flags = UserHalHelper.convertFlags(mUserHandleHelper, user); 1114 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1115 1116 // check if the user is last admin user. 1117 boolean isLastAdmin = false; 1118 if (UserHalHelper.isAdmin(halUser.flags)) { 1119 int size = usersInfo.existingUsers.length; 1120 int totalAdminUsers = 0; 1121 for (int i = 0; i < size; i++) { 1122 if (UserHalHelper.isAdmin(usersInfo.existingUsers[i].flags)) { 1123 totalAdminUsers++; 1124 } 1125 } 1126 if (totalAdminUsers == 1) { 1127 isLastAdmin = true; 1128 } 1129 } 1130 1131 // First remove user from android and then remove from HAL because HAL remove user is one 1132 // way call. 1133 // TODO(b/170887769): rename hasCallerRestrictions to fromCarDevicePolicyManager (or use an 1134 // int / enum to indicate if it's called from CarUserManager or CarDevicePolicyManager), as 1135 // it's counter-intuitive that it's "allowed even when disallowed" when it 1136 // "has caller restrictions" 1137 boolean overrideDevicePolicy = hasCallerRestrictions; 1138 int result = mUserManager.removeUserWhenPossible(user, overrideDevicePolicy); 1139 if (!UserManager.isRemoveResultSuccessful(result)) { 1140 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver); 1141 return; 1142 } 1143 1144 if (isLastAdmin) { 1145 Slogf.w(TAG, "Last admin user successfully removed or set ephemeral. User Id: %d", 1146 userId); 1147 } 1148 1149 switch (result) { 1150 case UserManager.REMOVE_RESULT_REMOVED: 1151 case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED: 1152 sendUserRemovalResult(userId, 1153 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_REMOVED 1154 : UserRemovalResult.STATUS_SUCCESSFUL, receiver); 1155 break; 1156 case UserManager.REMOVE_RESULT_DEFERRED: 1157 sendUserRemovalResult(userId, 1158 isLastAdmin ? UserRemovalResult.STATUS_SUCCESSFUL_LAST_ADMIN_SET_EPHEMERAL 1159 : UserRemovalResult.STATUS_SUCCESSFUL_SET_EPHEMERAL, receiver); 1160 break; 1161 default: 1162 sendUserRemovalResult(userId, UserRemovalResult.STATUS_ANDROID_FAILURE, receiver); 1163 } 1164 } 1165 1166 /** 1167 * Should be called by {@code ICarImpl} only. 1168 */ onUserRemoved(@onNull UserHandle user)1169 public void onUserRemoved(@NonNull UserHandle user) { 1170 if (DBG) { 1171 Slogf.d(TAG, "onUserRemoved: %s", user); 1172 } 1173 notifyHalUserRemoved(user); 1174 } 1175 notifyHalUserRemoved(@onNull UserHandle user)1176 private void notifyHalUserRemoved(@NonNull UserHandle user) { 1177 if (!isUserHalSupported()) return; 1178 1179 if (user == null) { 1180 Slogf.wtf(TAG, "notifyHalUserRemoved() called for null user"); 1181 return; 1182 } 1183 1184 int userId = user.getIdentifier(); 1185 1186 if (userId == USER_NULL) { 1187 Slogf.wtf(TAG, "notifyHalUserRemoved() called for USER_NULL"); 1188 return; 1189 } 1190 1191 synchronized (mLockUser) { 1192 if (mFailedToCreateUserIds.get(userId)) { 1193 if (DBG) { 1194 Slogf.d(TAG, "notifyHalUserRemoved(): skipping user %d", userId); 1195 } 1196 mFailedToCreateUserIds.delete(userId); 1197 return; 1198 } 1199 } 1200 1201 UserInfo halUser = new UserInfo(); 1202 halUser.userId = userId; 1203 halUser.flags = UserHalHelper.convertFlags(mUserHandleHelper, user); 1204 1205 RemoveUserRequest request = UserHalHelper.emptyRemoveUserRequest(); 1206 request.removedUserInfo = halUser; 1207 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1208 mHal.removeUser(request); 1209 } 1210 sendUserRemovalResult(@serIdInt int userId, @UserRemovalResult.Status int result, AndroidFuture<UserRemovalResult> receiver)1211 private void sendUserRemovalResult(@UserIdInt int userId, @UserRemovalResult.Status int result, 1212 AndroidFuture<UserRemovalResult> receiver) { 1213 EventLogHelper.writeCarUserServiceRemoveUserResp(userId, result); 1214 receiver.complete(new UserRemovalResult(result)); 1215 } 1216 sendUserSwitchUiCallback(@serIdInt int targetUserId)1217 private void sendUserSwitchUiCallback(@UserIdInt int targetUserId) { 1218 if (mUserSwitchUiReceiver == null) { 1219 Slogf.w(TAG, "No User switch UI receiver."); 1220 return; 1221 } 1222 1223 EventLogHelper.writeCarUserServiceSwitchUserUiReq(targetUserId); 1224 try { 1225 mUserSwitchUiReceiver.send(targetUserId, null); 1226 } catch (RemoteException e) { 1227 Slogf.e(TAG, "Error calling user switch UI receiver.", e); 1228 } 1229 } 1230 1231 /** 1232 * Used to create the initial user, even when it's disallowed by {@code DevicePolicyManager}. 1233 */ 1234 @Nullable createUserEvenWhenDisallowed(@ullable String name, @NonNull String userType, int flags)1235 UserHandle createUserEvenWhenDisallowed(@Nullable String name, @NonNull String userType, 1236 int flags) { 1237 synchronized (mLockUser) { 1238 if (mICarServiceHelper == null) { 1239 Slogf.wtf(TAG, "createUserEvenWhenDisallowed(): mICarServiceHelper not set yet", 1240 new Exception()); 1241 return null; 1242 } 1243 } 1244 1245 try { 1246 ICarServiceHelper iCarServiceHelper; 1247 synchronized (mLockUser) { 1248 iCarServiceHelper = mICarServiceHelper; 1249 } 1250 UserHandle user = iCarServiceHelper.createUserEvenWhenDisallowed(name, 1251 userType, flags); 1252 return user; 1253 } catch (RemoteException e) { 1254 Slogf.e(TAG, e, "createUserEvenWhenDisallowed(%s, %s, %d) failed", 1255 UserHelperLite.safeName(name), userType, flags); 1256 return null; 1257 } 1258 } 1259 1260 @Override createUser(@ullable String name, @NonNull String userType, int flags, int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver)1261 public void createUser(@Nullable String name, @NonNull String userType, int flags, 1262 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver) { 1263 createUser(name, userType, flags, timeoutMs, receiver, /* hasCallerRestrictions= */ false); 1264 } 1265 1266 /** 1267 * Internal implementation of {@code createUser()}, which is used by both 1268 * {@code ICarUserService} and {@code ICarDevicePolicyService}. 1269 * 1270 * @param hasCallerRestrictions when {@code true}, if the caller user is not an admin, it can 1271 * only create admin users 1272 */ createUser(@ullable String name, @NonNull String userType, int flags, int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver, boolean hasCallerRestrictions)1273 public void createUser(@Nullable String name, @NonNull String userType, int flags, 1274 int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver, 1275 boolean hasCallerRestrictions) { 1276 Objects.requireNonNull(userType, "user type cannot be null"); 1277 Objects.requireNonNull(receiver, "receiver cannot be null"); 1278 checkManageOrCreateUsersPermission(flags); 1279 EventLogHelper.writeCarUserServiceCreateUserReq(UserHelperLite.safeName(name), userType, 1280 flags, timeoutMs, hasCallerRestrictions ? 1 : 0); 1281 1282 UserHandle callingUser = Binder.getCallingUserHandle(); 1283 if (mUserManager.hasUserRestrictionForUser(UserManager.DISALLOW_ADD_USER, callingUser)) { 1284 String internalErrorMessage = String.format(ERROR_TEMPLATE_DISALLOW_ADD_USER, 1285 callingUser, UserManager.DISALLOW_ADD_USER); 1286 Slogf.w(TAG, internalErrorMessage); 1287 sendUserCreationFailure(receiver, UserCreationResult.STATUS_ANDROID_FAILURE, 1288 internalErrorMessage); 1289 return; 1290 } 1291 1292 mHandler.post(() -> handleCreateUser(name, userType, flags, timeoutMs, receiver, 1293 callingUser, hasCallerRestrictions)); 1294 } 1295 handleCreateUser(@ullable String name, @NonNull String userType, int flags, int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver, @NonNull UserHandle callingUser, boolean hasCallerRestrictions)1296 private void handleCreateUser(@Nullable String name, @NonNull String userType, 1297 int flags, int timeoutMs, @NonNull AndroidFuture<UserCreationResult> receiver, 1298 @NonNull UserHandle callingUser, boolean hasCallerRestrictions) { 1299 if (userType.equals(UserManager.USER_TYPE_FULL_GUEST) && flags != 0) { 1300 // Non-zero flags are not allowed when creating a guest user. 1301 String internalErroMessage = String 1302 .format(ERROR_TEMPLATE_INVALID_FLAGS_FOR_GUEST_CREATION, flags, name); 1303 Slogf.e(TAG, internalErroMessage); 1304 sendUserCreationFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST, 1305 internalErroMessage); 1306 return; 1307 } 1308 if (hasCallerRestrictions) { 1309 // Restrictions: 1310 // - type/flag can only be normal user, admin, or guest 1311 // - non-admin user can only create non-admin users 1312 1313 boolean validCombination; 1314 switch (userType) { 1315 case UserManager.USER_TYPE_FULL_SECONDARY: 1316 validCombination = flags == 0 1317 || (flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN; 1318 break; 1319 case UserManager.USER_TYPE_FULL_GUEST: 1320 validCombination = true; 1321 break; 1322 default: 1323 validCombination = false; 1324 } 1325 if (!validCombination) { 1326 String internalErrorMessage = String.format( 1327 ERROR_TEMPLATE_INVALID_USER_TYPE_AND_FLAGS_COMBINATION, userType, flags); 1328 1329 Slogf.d(TAG, internalErrorMessage); 1330 sendUserCreationFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST, 1331 internalErrorMessage); 1332 return; 1333 } 1334 1335 if (!mUserHandleHelper.isAdminUser(callingUser) 1336 && (flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) { 1337 String internalErrorMessage = String 1338 .format(ERROR_TEMPLATE_NON_ADMIN_CANNOT_CREATE_ADMIN_USERS, 1339 callingUser.getIdentifier()); 1340 Slogf.d(TAG, internalErrorMessage); 1341 sendUserCreationFailure(receiver, UserCreationResult.STATUS_INVALID_REQUEST, 1342 internalErrorMessage); 1343 return; 1344 } 1345 } 1346 1347 NewUserRequest newUserRequest; 1348 try { 1349 newUserRequest = getCreateUserRequest(name, userType, flags); 1350 } catch (Exception e) { 1351 Slogf.e(TAG, e, "Error creating new user request. name: %s UserType: %s and flags: %s", 1352 name, userType, flags); 1353 sendUserCreationResult(receiver, UserCreationResult.STATUS_ANDROID_FAILURE, 1354 UserManager.USER_OPERATION_ERROR_UNKNOWN, /* user= */ null, 1355 /* errorMessage= */ null, e.toString()); 1356 return; 1357 } 1358 1359 UserHandle newUser; 1360 try { 1361 NewUserResponse newUserResponse = mUserManager.createUser(newUserRequest); 1362 1363 if (!newUserResponse.isSuccessful()) { 1364 if (DBG) { 1365 Slogf.d(TAG, "um.createUser() returned null for user of type %s and flags %d", 1366 userType, flags); 1367 } 1368 sendUserCreationResult(receiver, UserCreationResult.STATUS_ANDROID_FAILURE, 1369 newUserResponse.getOperationResult(), /* user= */ null, 1370 /* errorMessage= */ null, /* internalErrorMessage= */ null); 1371 return; 1372 } 1373 1374 newUser = newUserResponse.getUser(); 1375 1376 if (DBG) { 1377 Slogf.d(TAG, "Created user: %s", newUser); 1378 } 1379 EventLogHelper.writeCarUserServiceCreateUserUserCreated(newUser.getIdentifier(), name, 1380 userType, flags); 1381 } catch (RuntimeException e) { 1382 Slogf.e(TAG, e, "Error creating user of type %s and flags %d", userType, flags); 1383 sendUserCreationResult(receiver, UserCreationResult.STATUS_ANDROID_FAILURE, 1384 UserManager.USER_OPERATION_ERROR_UNKNOWN, /* user= */ null, 1385 /* errorMessage= */ null, e.toString()); 1386 return; 1387 } 1388 1389 if (!isUserHalSupported()) { 1390 sendUserCreationResult(receiver, UserCreationResult.STATUS_SUCCESSFUL, 1391 /* androidFailureStatus= */ null , newUser, /* errorMessage= */ null, 1392 /* internalErrorMessage= */ null); 1393 return; 1394 } 1395 1396 CreateUserRequest request = UserHalHelper.emptyCreateUserRequest(); 1397 request.usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1398 if (!TextUtils.isEmpty(name)) { 1399 request.newUserName = name; 1400 } 1401 request.newUserInfo.userId = newUser.getIdentifier(); 1402 request.newUserInfo.flags = UserHalHelper.convertFlags(mUserHandleHelper, newUser); 1403 if (DBG) { 1404 Slogf.d(TAG, "Create user request: %s", request); 1405 } 1406 1407 try { 1408 mHal.createUser(request, timeoutMs, (status, resp) -> { 1409 String errorMessage = resp != null ? resp.errorMessage : null; 1410 int resultStatus = UserCreationResult.STATUS_HAL_INTERNAL_FAILURE; 1411 if (DBG) { 1412 Slogf.d(TAG, "createUserResponse: status=%s, resp=%s", 1413 UserHalHelper.halCallbackStatusToString(status), resp); 1414 } 1415 UserHandle user = null; // user returned in the result 1416 if (status != HalCallback.STATUS_OK || resp == null) { 1417 Slogf.w(TAG, "invalid callback status (%s) or null response (%s)", 1418 UserHalHelper.halCallbackStatusToString(status), resp); 1419 EventLogHelper.writeCarUserServiceCreateUserResp(status, resultStatus, 1420 errorMessage); 1421 removeCreatedUser(newUser, "HAL call failed with " 1422 + UserHalHelper.halCallbackStatusToString(status)); 1423 sendUserCreationResult(receiver, resultStatus, /* androidFailureStatus= */ null, 1424 user, errorMessage, /* internalErrorMessage= */ null); 1425 return; 1426 } 1427 1428 switch (resp.status) { 1429 case CreateUserStatus.SUCCESS: 1430 resultStatus = UserCreationResult.STATUS_SUCCESSFUL; 1431 user = newUser; 1432 break; 1433 case CreateUserStatus.FAILURE: 1434 // HAL failed to switch user 1435 resultStatus = UserCreationResult.STATUS_HAL_FAILURE; 1436 break; 1437 default: 1438 // Shouldn't happen because UserHalService validates the status 1439 Slogf.wtf(TAG, "Received invalid user switch status from HAL: %s", resp); 1440 } 1441 EventLogHelper.writeCarUserServiceCreateUserResp(status, resultStatus, 1442 errorMessage); 1443 if (user == null) { 1444 removeCreatedUser(newUser, "HAL returned " 1445 + UserCreationResult.statusToString(resultStatus)); 1446 } 1447 sendUserCreationResult(receiver, resultStatus, /* androidFailureStatus= */ null, 1448 user, errorMessage, /* internalErrorMessage= */ null); 1449 }); 1450 } catch (Exception e) { 1451 Slogf.w(TAG, e, "mHal.createUser(%s) failed", request); 1452 removeCreatedUser(newUser, "mHal.createUser() failed"); 1453 sendUserCreationFailure(receiver, UserCreationResult.STATUS_HAL_INTERNAL_FAILURE, 1454 e.toString()); 1455 } 1456 } 1457 getCreateUserRequest(String name, String userType, int flags)1458 private NewUserRequest getCreateUserRequest(String name, String userType, int flags) { 1459 NewUserRequest.Builder builder = new NewUserRequest.Builder().setName(name) 1460 .setUserType(userType); 1461 if ((flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) { 1462 builder.setAdmin(); 1463 } 1464 1465 if ((flags & UserManagerHelper.FLAG_EPHEMERAL) == UserManagerHelper.FLAG_EPHEMERAL) { 1466 builder.setEphemeral(); 1467 } 1468 1469 return builder.build(); 1470 } 1471 removeCreatedUser(@onNull UserHandle user, @NonNull String reason)1472 private void removeCreatedUser(@NonNull UserHandle user, @NonNull String reason) { 1473 Slogf.i(TAG, "removing user %s reason: %s", user, reason); 1474 1475 int userId = user.getIdentifier(); 1476 EventLogHelper.writeCarUserServiceCreateUserUserRemoved(userId, reason); 1477 1478 synchronized (mLockUser) { 1479 mFailedToCreateUserIds.put(userId, true); 1480 } 1481 1482 try { 1483 if (!mUserManager.removeUser(user)) { 1484 Slogf.w(TAG, "Failed to remove user %s", user); 1485 } 1486 } catch (Exception e) { 1487 Slogf.e(TAG, e, "Failed to remove user %s", user); 1488 } 1489 } 1490 1491 @Override getUserIdentificationAssociation( @serIdentificationAssociationType int[] types)1492 public UserIdentificationAssociationResponse getUserIdentificationAssociation( 1493 @UserIdentificationAssociationType int[] types) { 1494 if (!isUserHalUserAssociationSupported()) { 1495 return UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED); 1496 } 1497 1498 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 1499 checkManageOrCreateUsersPermission("getUserIdentificationAssociation"); 1500 1501 int uid = getCallingUid(); 1502 int userId = getCallingUserHandle().getIdentifier(); 1503 EventLogHelper.writeCarUserServiceGetUserAuthReq(uid, userId, types.length); 1504 1505 UserIdentificationGetRequest request = UserHalHelper.emptyUserIdentificationGetRequest(); 1506 request.userInfo.userId = userId; 1507 request.userInfo.flags = getHalUserInfoFlags(userId); 1508 1509 request.numberAssociationTypes = types.length; 1510 ArrayList<Integer> associationTypes = new ArrayList<>(types.length); 1511 for (int i = 0; i < types.length; i++) { 1512 associationTypes.add(types[i]); 1513 } 1514 request.associationTypes = toIntArray(associationTypes); 1515 1516 UserIdentificationResponse halResponse = mHal.getUserAssociation(request); 1517 if (halResponse == null) { 1518 Slogf.w(TAG, "getUserIdentificationAssociation(): HAL returned null for %s", 1519 Arrays.toString(types)); 1520 return UserIdentificationAssociationResponse.forFailure(); 1521 } 1522 1523 int[] values = new int[halResponse.associations.length]; 1524 for (int i = 0; i < values.length; i++) { 1525 values[i] = halResponse.associations[i].value; 1526 } 1527 EventLogHelper.writeCarUserServiceGetUserAuthResp(values.length); 1528 1529 return UserIdentificationAssociationResponse.forSuccess(values, halResponse.errorMessage); 1530 } 1531 1532 @Override setUserIdentificationAssociation(int timeoutMs, @UserIdentificationAssociationType int[] types, @UserIdentificationAssociationSetValue int[] values, AndroidFuture<UserIdentificationAssociationResponse> result)1533 public void setUserIdentificationAssociation(int timeoutMs, 1534 @UserIdentificationAssociationType int[] types, 1535 @UserIdentificationAssociationSetValue int[] values, 1536 AndroidFuture<UserIdentificationAssociationResponse> result) { 1537 if (!isUserHalUserAssociationSupported()) { 1538 result.complete( 1539 UserIdentificationAssociationResponse.forFailure(VEHICLE_HAL_NOT_SUPPORTED)); 1540 return; 1541 } 1542 1543 Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type"); 1544 Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value"); 1545 if (types.length != values.length) { 1546 throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values (" 1547 + Arrays.toString(values) + ") should have the same length"); 1548 } 1549 checkManageOrCreateUsersPermission("setUserIdentificationAssociation"); 1550 1551 int uid = getCallingUid(); 1552 int userId = getCallingUserHandle().getIdentifier(); 1553 EventLogHelper.writeCarUserServiceSetUserAuthReq(uid, userId, types.length); 1554 1555 UserIdentificationSetRequest request = UserHalHelper.emptyUserIdentificationSetRequest(); 1556 request.userInfo.userId = userId; 1557 request.userInfo.flags = getHalUserInfoFlags(userId); 1558 1559 request.numberAssociations = types.length; 1560 ArrayList<UserIdentificationSetAssociation> associations = new ArrayList<>(); 1561 for (int i = 0; i < types.length; i++) { 1562 UserIdentificationSetAssociation association = new UserIdentificationSetAssociation(); 1563 association.type = types[i]; 1564 association.value = values[i]; 1565 associations.add(association); 1566 } 1567 request.associations = 1568 associations.toArray(new UserIdentificationSetAssociation[associations.size()]); 1569 1570 mHal.setUserAssociation(timeoutMs, request, (status, resp) -> { 1571 if (status != HalCallback.STATUS_OK || resp == null) { 1572 Slogf.w(TAG, "setUserIdentificationAssociation(): invalid callback status (%s) for " 1573 + "response %s", UserHalHelper.halCallbackStatusToString(status), resp); 1574 if (resp == null || TextUtils.isEmpty(resp.errorMessage)) { 1575 EventLogHelper.writeCarUserServiceSetUserAuthResp(0, /* errorMessage= */ ""); 1576 result.complete(UserIdentificationAssociationResponse.forFailure()); 1577 return; 1578 } 1579 EventLogHelper.writeCarUserServiceSetUserAuthResp(0, resp.errorMessage); 1580 result.complete( 1581 UserIdentificationAssociationResponse.forFailure(resp.errorMessage)); 1582 return; 1583 } 1584 int respSize = resp.associations.length; 1585 EventLogHelper.writeCarUserServiceSetUserAuthResp(respSize, resp.errorMessage); 1586 1587 int[] responseTypes = new int[respSize]; 1588 for (int i = 0; i < respSize; i++) { 1589 responseTypes[i] = resp.associations[i].value; 1590 } 1591 UserIdentificationAssociationResponse response = UserIdentificationAssociationResponse 1592 .forSuccess(responseTypes, resp.errorMessage); 1593 if (DBG) { 1594 Slogf.d(TAG, "setUserIdentificationAssociation(): resp=%s, converted=%s", resp, 1595 response); 1596 } 1597 result.complete(response); 1598 }); 1599 } 1600 1601 /** 1602 * Gets the User HAL flags for the given user. 1603 * 1604 * @throws IllegalArgumentException if the user does not exist. 1605 */ getHalUserInfoFlags(@serIdInt int userId)1606 private int getHalUserInfoFlags(@UserIdInt int userId) { 1607 UserHandle user = mUserHandleHelper.getExistingUserHandle(userId); 1608 Preconditions.checkArgument(user != null, "no user for id %d", userId); 1609 return UserHalHelper.convertFlags(mUserHandleHelper, user); 1610 } 1611 sendUserSwitchResult(@onNull AndroidFuture<UserSwitchResult> receiver, boolean isLogout, @UserSwitchResult.Status int userSwitchStatus)1612 static void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver, 1613 boolean isLogout, @UserSwitchResult.Status int userSwitchStatus) { 1614 sendUserSwitchResult(receiver, isLogout, HalCallback.STATUS_INVALID, userSwitchStatus, 1615 /* androidFailureStatus= */ null, /* errorMessage= */ null); 1616 } 1617 sendUserSwitchResult(@onNull AndroidFuture<UserSwitchResult> receiver, boolean isLogout, @HalCallback.HalCallbackStatus int halCallbackStatus, @UserSwitchResult.Status int userSwitchStatus, @Nullable Integer androidFailureStatus, @Nullable String errorMessage)1618 static void sendUserSwitchResult(@NonNull AndroidFuture<UserSwitchResult> receiver, 1619 boolean isLogout, @HalCallback.HalCallbackStatus int halCallbackStatus, 1620 @UserSwitchResult.Status int userSwitchStatus, @Nullable Integer androidFailureStatus, 1621 @Nullable String errorMessage) { 1622 if (isLogout) { 1623 EventLogHelper.writeCarUserServiceLogoutUserResp(halCallbackStatus, userSwitchStatus, 1624 errorMessage); 1625 } else { 1626 EventLogHelper.writeCarUserServiceSwitchUserResp(halCallbackStatus, userSwitchStatus, 1627 errorMessage); 1628 } 1629 receiver.complete( 1630 new UserSwitchResult(userSwitchStatus, androidFailureStatus, errorMessage)); 1631 } 1632 sendUserCreationFailure(AndroidFuture<UserCreationResult> receiver, @UserCreationResult.Status int status, String internalErrorMessage)1633 static void sendUserCreationFailure(AndroidFuture<UserCreationResult> receiver, 1634 @UserCreationResult.Status int status, String internalErrorMessage) { 1635 sendUserCreationResult(receiver, status, /* androidStatus= */ null, /* user= */ null, 1636 /* errorMessage= */ null, internalErrorMessage); 1637 } 1638 sendUserCreationResult(AndroidFuture<UserCreationResult> receiver, @UserCreationResult.Status int status, @Nullable Integer androidFailureStatus, @NonNull UserHandle user, @Nullable String errorMessage, @Nullable String internalErrorMessage)1639 private static void sendUserCreationResult(AndroidFuture<UserCreationResult> receiver, 1640 @UserCreationResult.Status int status, @Nullable Integer androidFailureStatus, 1641 @NonNull UserHandle user, @Nullable String errorMessage, 1642 @Nullable String internalErrorMessage) { 1643 if (TextUtils.isEmpty(errorMessage)) { 1644 errorMessage = null; 1645 } 1646 if (TextUtils.isEmpty(internalErrorMessage)) { 1647 internalErrorMessage = null; 1648 } 1649 1650 receiver.complete(new UserCreationResult(status, androidFailureStatus, user, errorMessage, 1651 internalErrorMessage)); 1652 } 1653 1654 /** 1655 * Calls activity manager for user switch. 1656 * 1657 * <p><b>NOTE</b> This method is meant to be called just by UserHalService. 1658 * 1659 * @param requestId for the user switch request 1660 * @param targetUserId of the target user 1661 * 1662 * @hide 1663 */ switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId)1664 public void switchAndroidUserFromHal(int requestId, @UserIdInt int targetUserId) { 1665 EventLogHelper.writeCarUserServiceSwitchUserFromHalReq(requestId, targetUserId); 1666 Slogf.i(TAG, "User hal requested a user switch. Target user id is %d", targetUserId); 1667 1668 boolean result = mAm.switchUser(UserHandle.of(targetUserId)); 1669 if (result) { 1670 updateUserSwitchInProcess(requestId, targetUserId); 1671 } else { 1672 postSwitchHalResponse(requestId, targetUserId); 1673 } 1674 } 1675 updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId)1676 private void updateUserSwitchInProcess(int requestId, @UserIdInt int targetUserId) { 1677 synchronized (mLockUser) { 1678 if (mUserIdForUserSwitchInProcess != USER_NULL) { 1679 // Some other user switch is in process. 1680 Slogf.w(TAG, "User switch for user id %d is in process. Abandoning it as a new user" 1681 + " switch is requested for the target user %d", 1682 mUserIdForUserSwitchInProcess, targetUserId); 1683 } 1684 mUserIdForUserSwitchInProcess = targetUserId; 1685 mRequestIdForUserSwitchInProcess = requestId; 1686 } 1687 } 1688 postSwitchHalResponse(int requestId, @UserIdInt int targetUserId)1689 private void postSwitchHalResponse(int requestId, @UserIdInt int targetUserId) { 1690 if (!isUserHalSupported()) return; 1691 1692 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper); 1693 EventLogHelper.writeCarUserServicePostSwitchUserReq(targetUserId, 1694 usersInfo.currentUser.userId); 1695 SwitchUserRequest request = createUserSwitchRequest(targetUserId, usersInfo); 1696 request.requestId = requestId; 1697 mHal.postSwitchResponse(request); 1698 } 1699 createUserSwitchRequest(@serIdInt int targetUserId, @NonNull UsersInfo usersInfo)1700 private SwitchUserRequest createUserSwitchRequest(@UserIdInt int targetUserId, 1701 @NonNull UsersInfo usersInfo) { 1702 UserHandle targetUser = mUserHandleHelper.getExistingUserHandle(targetUserId); 1703 UserInfo halTargetUser = new UserInfo(); 1704 halTargetUser.userId = targetUser.getIdentifier(); 1705 halTargetUser.flags = UserHalHelper.convertFlags(mUserHandleHelper, targetUser); 1706 SwitchUserRequest request = UserHalHelper.emptySwitchUserRequest(); 1707 request.targetUser = halTargetUser; 1708 request.usersInfo = usersInfo; 1709 return request; 1710 } 1711 1712 /** 1713 * Checks if the User HAL is supported. 1714 */ isUserHalSupported()1715 public boolean isUserHalSupported() { 1716 return mHal.isSupported(); 1717 } 1718 1719 /** 1720 * Checks if the User HAL user association is supported. 1721 */ 1722 @Override isUserHalUserAssociationSupported()1723 public boolean isUserHalUserAssociationSupported() { 1724 return mHal.isUserAssociationSupported(); 1725 } 1726 1727 /** 1728 * Sets a callback which is invoked before user switch. 1729 * 1730 * <p> 1731 * This method should only be called by the Car System UI. The purpose of this call is to notify 1732 * Car System UI to show the user switch UI before the user switch. 1733 */ 1734 @Override setUserSwitchUiCallback(@onNull ICarResultReceiver receiver)1735 public void setUserSwitchUiCallback(@NonNull ICarResultReceiver receiver) { 1736 checkManageUsersPermission("setUserSwitchUiCallback"); 1737 1738 // Confirm that caller is system UI. 1739 String systemUiPackageName = PackageManagerHelper.getSystemUiPackageName(mContext); 1740 1741 try { 1742 int systemUiUid = mContext 1743 .createContextAsUser(UserHandle.SYSTEM, /* flags= */ 0).getPackageManager() 1744 .getPackageUid(systemUiPackageName, PackageManager.MATCH_SYSTEM_ONLY); 1745 int callerUid = Binder.getCallingUid(); 1746 if (systemUiUid != callerUid) { 1747 throw new SecurityException("Invalid caller. Only" + systemUiPackageName 1748 + " is allowed to make this call"); 1749 } 1750 } catch (NameNotFoundException e) { 1751 throw new IllegalStateException("Package " + systemUiPackageName + " not found."); 1752 } 1753 1754 mUserSwitchUiReceiver = receiver; 1755 } 1756 updateDefaultUserRestriction()1757 private void updateDefaultUserRestriction() { 1758 // We want to set restrictions on system and guest users only once. These are persisted 1759 // onto disk, so it's sufficient to do it once + we minimize the number of disk writes. 1760 if (Settings.Global.getInt(mContext.getContentResolver(), 1761 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, /* default= */ 0) != 0) { 1762 return; 1763 } 1764 // Only apply the system user restrictions if the system user is headless. 1765 if (UserManager.isHeadlessSystemUserMode()) { 1766 setSystemUserRestrictions(); 1767 } 1768 Settings.Global.putInt(mContext.getContentResolver(), 1769 CarSettings.Global.DEFAULT_USER_RESTRICTIONS_SET, 1); 1770 } 1771 isPersistentUser(@serIdInt int userId)1772 private boolean isPersistentUser(@UserIdInt int userId) { 1773 return !mUserHandleHelper.isEphemeralUser(UserHandle.of(userId)); 1774 } 1775 1776 /** 1777 * Adds a new {@link UserLifecycleListener} with {@code filter} to selectively listen to user 1778 * activity events. 1779 */ addUserLifecycleListener(@ullable UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener)1780 public void addUserLifecycleListener(@Nullable UserLifecycleEventFilter filter, 1781 @NonNull UserLifecycleListener listener) { 1782 Objects.requireNonNull(listener, "listener cannot be null"); 1783 mHandler.post(() -> mUserLifecycleListeners.add( 1784 new InternalLifecycleListener(listener, filter))); 1785 } 1786 1787 /** 1788 * Removes previously added {@link UserLifecycleListener}. 1789 */ removeUserLifecycleListener(@onNull UserLifecycleListener listener)1790 public void removeUserLifecycleListener(@NonNull UserLifecycleListener listener) { 1791 Objects.requireNonNull(listener, "listener cannot be null"); 1792 mHandler.post(() -> { 1793 for (int i = 0; i < mUserLifecycleListeners.size(); i++) { 1794 if (listener.equals(mUserLifecycleListeners.get(i).listener)) { 1795 mUserLifecycleListeners.remove(i); 1796 } 1797 } 1798 }); 1799 } 1800 onUserUnlocked(@serIdInt int userId)1801 private void onUserUnlocked(@UserIdInt int userId) { 1802 ArrayList<Runnable> tasks = null; 1803 synchronized (mLockUser) { 1804 sendPostSwitchToHalLocked(userId); 1805 if (userId == UserHandle.SYSTEM.getIdentifier()) { 1806 if (!mUser0Unlocked) { // user 0, unlocked, do this only once 1807 updateDefaultUserRestriction(); 1808 tasks = new ArrayList<>(mUser0UnlockTasks); 1809 mUser0UnlockTasks.clear(); 1810 mUser0Unlocked = true; 1811 } 1812 } else { // none user0 1813 Integer user = userId; 1814 if (isPersistentUser(userId)) { 1815 // current foreground user should stay in top priority. 1816 if (userId == ActivityManager.getCurrentUser()) { 1817 mBackgroundUsersToRestart.remove(user); 1818 mBackgroundUsersToRestart.add(0, user); 1819 } 1820 // -1 for user 0 1821 if (mBackgroundUsersToRestart.size() > (mMaxRunningUsers - 1)) { 1822 int userToDrop = mBackgroundUsersToRestart.get( 1823 mBackgroundUsersToRestart.size() - 1); 1824 Slogf.i(TAG, "New user (%d) unlocked, dropping least recently user from " 1825 + "restart list (%s)", userId, userToDrop); 1826 // Drop the least recently used user. 1827 mBackgroundUsersToRestart.remove(mBackgroundUsersToRestart.size() - 1); 1828 } 1829 } 1830 } 1831 } 1832 if (tasks != null) { 1833 int tasksSize = tasks.size(); 1834 if (tasksSize > 0) { 1835 Slogf.d(TAG, "User0 unlocked, run queued tasks size: %d", tasksSize); 1836 for (int i = 0; i < tasksSize; i++) { 1837 tasks.get(i).run(); 1838 } 1839 } 1840 } 1841 } 1842 1843 /** 1844 * Starts the specified user in the background. 1845 * 1846 * @param userId user to start in background 1847 * @param receiver to post results 1848 */ startUserInBackground(@serIdInt int userId, @NonNull AndroidFuture<UserStartResult> receiver)1849 public void startUserInBackground(@UserIdInt int userId, 1850 @NonNull AndroidFuture<UserStartResult> receiver) { 1851 checkManageOrCreateUsersPermission("startUserInBackground"); 1852 EventLogHelper.writeCarUserServiceStartUserInBackgroundReq(userId); 1853 1854 mHandler.post(() -> handleStartUserInBackground(userId, receiver)); 1855 } 1856 handleStartUserInBackground(@serIdInt int userId, @NonNull AndroidFuture<UserStartResult> receiver)1857 private void handleStartUserInBackground(@UserIdInt int userId, 1858 @NonNull AndroidFuture<UserStartResult> receiver) { 1859 // If the requested user is the current user, do nothing and return success. 1860 if (ActivityManager.getCurrentUser() == userId) { 1861 sendUserStartResult( 1862 userId, UserStartResult.STATUS_SUCCESSFUL_USER_IS_CURRENT_USER, receiver); 1863 return; 1864 } 1865 // If requested user does not exist, return error. 1866 if (mUserHandleHelper.getExistingUserHandle(userId) == null) { 1867 Slogf.w(TAG, "User %d does not exist", userId); 1868 sendUserStartResult(userId, UserStartResult.STATUS_USER_DOES_NOT_EXIST, receiver); 1869 return; 1870 } 1871 1872 if (!ActivityManagerHelper.startUserInBackground(userId)) { 1873 Slogf.w(TAG, "Failed to start user %d in background", userId); 1874 sendUserStartResult(userId, UserStartResult.STATUS_ANDROID_FAILURE, receiver); 1875 return; 1876 } 1877 1878 // TODO(b/181331178): We are not updating mBackgroundUsersToRestart or 1879 // mBackgroundUsersRestartedHere, which were only used for the garage mode. Consider 1880 // renaming them to make it more clear. 1881 sendUserStartResult(userId, UserStartResult.STATUS_SUCCESSFUL, receiver); 1882 } 1883 sendUserStartResult(@serIdInt int userId, @UserStartResult.Status int result, @NonNull AndroidFuture<UserStartResult> receiver)1884 private void sendUserStartResult(@UserIdInt int userId, @UserStartResult.Status int result, 1885 @NonNull AndroidFuture<UserStartResult> receiver) { 1886 EventLogHelper.writeCarUserServiceStartUserInBackgroundResp(userId, result); 1887 receiver.complete(new UserStartResult(result)); 1888 } 1889 1890 /** 1891 * Starts all background users that were active in system. 1892 * 1893 * @return list of background users started successfully. 1894 */ 1895 @NonNull startAllBackgroundUsersInGarageMode()1896 public ArrayList<Integer> startAllBackgroundUsersInGarageMode() { 1897 synchronized (mLockUser) { 1898 if (!mStartBackgroundUsersOnGarageMode) { 1899 Slogf.i(TAG, "Background users are not started as mStartBackgroundUsersOnGarageMode" 1900 + " is false."); 1901 return new ArrayList<>(); 1902 } 1903 } 1904 1905 ArrayList<Integer> users; 1906 synchronized (mLockUser) { 1907 users = new ArrayList<>(mBackgroundUsersToRestart); 1908 mBackgroundUsersRestartedHere.clear(); 1909 mBackgroundUsersRestartedHere.addAll(mBackgroundUsersToRestart); 1910 } 1911 ArrayList<Integer> startedUsers = new ArrayList<>(); 1912 for (Integer user : users) { 1913 if (user == ActivityManager.getCurrentUser()) { 1914 continue; 1915 } 1916 if (ActivityManagerHelper.startUserInBackground(user)) { 1917 if (mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user))) { 1918 // already unlocked / unlocking. No need to unlock. 1919 startedUsers.add(user); 1920 } else if (ActivityManagerHelper.unlockUser(user)) { 1921 startedUsers.add(user); 1922 } else { // started but cannot unlock 1923 Slogf.w(TAG, "Background user started but cannot be unlocked: %s", user); 1924 if (mUserManager.isUserRunning(UserHandle.of(user))) { 1925 // add to started list so that it can be stopped later. 1926 startedUsers.add(user); 1927 } 1928 } 1929 } 1930 } 1931 // Keep only users that were re-started in mBackgroundUsersRestartedHere 1932 synchronized (mLockUser) { 1933 ArrayList<Integer> usersToRemove = new ArrayList<>(); 1934 for (Integer user : mBackgroundUsersToRestart) { 1935 if (!startedUsers.contains(user)) { 1936 usersToRemove.add(user); 1937 } 1938 } 1939 mBackgroundUsersRestartedHere.removeAll(usersToRemove); 1940 } 1941 return startedUsers; 1942 } 1943 1944 /** 1945 * Stops the specified background user. 1946 * 1947 * @param userId user to stop 1948 * @param receiver to post results 1949 */ stopUser(@serIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver)1950 public void stopUser(@UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) { 1951 checkManageOrCreateUsersPermission("stopUser"); 1952 EventLogHelper.writeCarUserServiceStopUserReq(userId); 1953 1954 mHandler.post(() -> handleStopUser(userId, receiver)); 1955 } 1956 handleStopUser( @serIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver)1957 private void handleStopUser( 1958 @UserIdInt int userId, @NonNull AndroidFuture<UserStopResult> receiver) { 1959 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId); 1960 sendUserStopResult(userId, userStopStatus, receiver); 1961 } 1962 sendUserStopResult(@serIdInt int userId, @UserStopResult.Status int result, @NonNull AndroidFuture<UserStopResult> receiver)1963 private void sendUserStopResult(@UserIdInt int userId, @UserStopResult.Status int result, 1964 @NonNull AndroidFuture<UserStopResult> receiver) { 1965 EventLogHelper.writeCarUserServiceStopUserResp(userId, result); 1966 receiver.complete(new UserStopResult(result)); 1967 } 1968 stopBackgroundUserInternal(@serIdInt int userId)1969 private @UserStopResult.Status int stopBackgroundUserInternal(@UserIdInt int userId) { 1970 int r = ActivityManagerHelper.stopUserWithDelayedLocking(userId, true); 1971 switch(r) { 1972 case USER_OP_SUCCESS: 1973 return UserStopResult.STATUS_SUCCESSFUL; 1974 case USER_OP_ERROR_IS_SYSTEM: 1975 Slogf.w(TAG, "Cannot stop the system user: %d", userId); 1976 return UserStopResult.STATUS_FAILURE_SYSTEM_USER; 1977 case USER_OP_IS_CURRENT: 1978 Slogf.w(TAG, "Cannot stop the current user: %d", userId); 1979 return UserStopResult.STATUS_FAILURE_CURRENT_USER; 1980 case USER_OP_UNKNOWN_USER: 1981 Slogf.w(TAG, "Cannot stop the user that does not exist: %d", userId); 1982 return UserStopResult.STATUS_USER_DOES_NOT_EXIST; 1983 default: 1984 Slogf.w(TAG, "stopUser failed, user: %d, err: %d", userId, r); 1985 } 1986 return UserStopResult.STATUS_ANDROID_FAILURE; 1987 } 1988 1989 /** 1990 * Sets boolean to control background user operations during garage mode. 1991 */ setStartBackgroundUsersOnGarageMode(boolean enable)1992 public void setStartBackgroundUsersOnGarageMode(boolean enable) { 1993 synchronized (mLockUser) { 1994 mStartBackgroundUsersOnGarageMode = enable; 1995 } 1996 } 1997 1998 /** 1999 * Stops a background user. 2000 * 2001 * @return whether stopping succeeds. 2002 */ stopBackgroundUserInGagageMode(@serIdInt int userId)2003 public boolean stopBackgroundUserInGagageMode(@UserIdInt int userId) { 2004 synchronized (mLockUser) { 2005 if (!mStartBackgroundUsersOnGarageMode) { 2006 Slogf.i(TAG, "Background users are not stopped as mStartBackgroundUsersOnGarageMode" 2007 + " is false."); 2008 return false; 2009 } 2010 } 2011 2012 @UserStopResult.Status int userStopStatus = stopBackgroundUserInternal(userId); 2013 if (UserStopResult.isSuccess(userStopStatus)) { 2014 // Remove the stopped user from the mBackgroundUserRestartedHere list. 2015 synchronized (mLockUser) { 2016 mBackgroundUsersRestartedHere.remove(Integer.valueOf(userId)); 2017 } 2018 return true; 2019 } 2020 return false; 2021 } 2022 2023 /** 2024 * Notifies all registered {@link UserLifecycleListener} with the event passed as argument. 2025 */ onUserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int fromUserId, @UserIdInt int toUserId)2026 public void onUserLifecycleEvent(@UserLifecycleEventType int eventType, 2027 @UserIdInt int fromUserId, @UserIdInt int toUserId) { 2028 if (DBG) { 2029 Slogf.d(TAG, "onUserLifecycleEvent(): event=%d, from=%d, to=%d", eventType, fromUserId, 2030 toUserId); 2031 } 2032 int userId = toUserId; 2033 2034 // Handle special cases first... 2035 switch (eventType) { 2036 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING: 2037 onUserSwitching(fromUserId, toUserId); 2038 break; 2039 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED: 2040 onUserUnlocked(userId); 2041 break; 2042 case CarUserManager.USER_LIFECYCLE_EVENT_TYPE_REMOVED: 2043 onUserRemoved(UserHandle.of(userId)); 2044 break; 2045 default: 2046 } 2047 2048 // ...then notify listeners. 2049 UserLifecycleEvent event = new UserLifecycleEvent(eventType, fromUserId, userId); 2050 2051 mHandler.post(() -> { 2052 handleNotifyServiceUserLifecycleListeners(event); 2053 // POST_UNLOCKED event is meant only for internal service listeners. Skip sending it to 2054 // app listeners. 2055 if (eventType != CarUserManager.USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED) { 2056 handleNotifyAppUserLifecycleListeners(event); 2057 } 2058 }); 2059 } 2060 sendPostSwitchToHalLocked(@serIdInt int userId)2061 private void sendPostSwitchToHalLocked(@UserIdInt int userId) { 2062 int userIdForUserSwitchInProcess; 2063 int requestIdForUserSwitchInProcess; 2064 synchronized (mLockUser) { 2065 if (mUserIdForUserSwitchInProcess == USER_NULL 2066 || mUserIdForUserSwitchInProcess != userId 2067 || mRequestIdForUserSwitchInProcess == 0) { 2068 Slogf.d(TAG, "No user switch request Id. No android post switch sent."); 2069 return; 2070 } 2071 userIdForUserSwitchInProcess = mUserIdForUserSwitchInProcess; 2072 requestIdForUserSwitchInProcess = mRequestIdForUserSwitchInProcess; 2073 2074 mUserIdForUserSwitchInProcess = USER_NULL; 2075 mRequestIdForUserSwitchInProcess = 0; 2076 } 2077 postSwitchHalResponse(requestIdForUserSwitchInProcess, userIdForUserSwitchInProcess); 2078 } 2079 handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event)2080 private void handleNotifyAppUserLifecycleListeners(UserLifecycleEvent event) { 2081 int listenersSize = mAppLifecycleListeners.size(); 2082 if (listenersSize == 0) { 2083 Slogf.d(TAG, "No app listener to be notified of %s", event); 2084 return; 2085 } 2086 // Must use a different TimingsTraceLog because it's another thread 2087 if (DBG) { 2088 Slogf.d(TAG, "Notifying %d app listeners of %s", listenersSize, event); 2089 } 2090 int userId = event.getUserId(); 2091 TimingsTraceLog t = new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE); 2092 int eventType = event.getEventType(); 2093 t.traceBegin("notify-app-listeners-user-" + userId + "-event-" + eventType); 2094 for (int i = 0; i < listenersSize; i++) { 2095 AppLifecycleListener listener = mAppLifecycleListeners.valueAt(i); 2096 if (eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_CREATED 2097 || eventType == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_REMOVED) { 2098 PlatformVersion platformVersion = Car.getPlatformVersion(); 2099 // Perform platform version check to ensure the support for these new events 2100 // is consistent with the platform version declared in their ApiRequirements. 2101 if (!platformVersion.isAtLeast(PlatformVersion.VERSION_CODES.TIRAMISU_1)) { 2102 if (DBG) { 2103 Slogf.d(TAG, "Skipping app listener %s for event %s due to unsupported" 2104 + " car platform version %s.", listener, event, platformVersion); 2105 } 2106 continue; 2107 } 2108 // Perform target car version check to ensure only apps expecting the new 2109 // lifecycle event types will have the events sent to them. 2110 // TODO(b/235524989): Cache the target car version for packages in 2111 // CarPackageManagerService. 2112 CarVersion targetCarVersion = mCarPackageManagerService.getTargetCarVersion( 2113 listener.packageName); 2114 if (!targetCarVersion.isAtLeast(CarVersion.VERSION_CODES.TIRAMISU_1)) { 2115 if (DBG) { 2116 Slogf.d(TAG, "Skipping app listener %s for event %s due to incompatible" 2117 + " target car version %s.", listener, event, targetCarVersion); 2118 } 2119 continue; 2120 } 2121 } 2122 if (!listener.applyFilters(event)) { 2123 if (DBG) { 2124 Slogf.d(TAG, "Skipping app listener %s for event %s due to the filters" 2125 + " evaluated to false.", listener, event); 2126 } 2127 continue; 2128 } 2129 Bundle data = new Bundle(); 2130 data.putInt(CarUserManager.BUNDLE_PARAM_ACTION, eventType); 2131 2132 int fromUserId = event.getPreviousUserId(); 2133 if (fromUserId != USER_NULL) { 2134 data.putInt(CarUserManager.BUNDLE_PARAM_PREVIOUS_USER_ID, fromUserId); 2135 } 2136 Slogf.d(TAG, "Notifying app listener %s", listener); 2137 EventLogHelper.writeCarUserServiceNotifyAppLifecycleListener(listener.uid, 2138 listener.packageName, eventType, fromUserId, userId); 2139 try { 2140 t.traceBegin("notify-app-listener-" + listener.toShortString()); 2141 listener.receiver.send(userId, data); 2142 } catch (RemoteException e) { 2143 Slogf.e(TAG, e, "Error calling lifecycle listener %s", listener); 2144 } finally { 2145 t.traceEnd(); 2146 } 2147 } 2148 t.traceEnd(); // notify-app-listeners-user-USERID-event-EVENT_TYPE 2149 } 2150 handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event)2151 private void handleNotifyServiceUserLifecycleListeners(UserLifecycleEvent event) { 2152 TimingsTraceLog t = new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE); 2153 if (mUserLifecycleListeners.isEmpty()) { 2154 Slogf.w(TAG, "No internal UserLifecycleListeners registered to notify event %s", 2155 event); 2156 return; 2157 } 2158 int userId = event.getUserId(); 2159 int eventType = event.getEventType(); 2160 t.traceBegin("notify-listeners-user-" + userId + "-event-" + eventType); 2161 for (InternalLifecycleListener listener : mUserLifecycleListeners) { 2162 String listenerName = FunctionalUtils.getLambdaName(listener); 2163 UserLifecycleEventFilter filter = listener.filter; 2164 if (filter != null && !filter.apply(event)) { 2165 if (DBG) { 2166 Slogf.d(TAG, "Skipping service listener %s for event %s due to the filter %s" 2167 + " evaluated to false", listenerName, event, filter); 2168 } 2169 continue; 2170 } 2171 if (DBG) { 2172 Slogf.d(TAG, "Notifying %d service listeners of %s", mUserLifecycleListeners.size(), 2173 event); 2174 } 2175 EventLogHelper.writeCarUserServiceNotifyInternalLifecycleListener(listenerName, 2176 eventType, event.getPreviousUserId(), userId); 2177 try { 2178 t.traceBegin("notify-listener-" + listenerName); 2179 listener.listener.onEvent(event); 2180 } catch (RuntimeException e) { 2181 Slogf.e(TAG, e , "Exception raised when invoking onEvent for %s", listenerName); 2182 } finally { 2183 t.traceEnd(); 2184 } 2185 } 2186 t.traceEnd(); // notify-listeners-user-USERID-event-EVENT_TYPE 2187 } 2188 onUserSwitching(@serIdInt int fromUserId, @UserIdInt int toUserId)2189 private void onUserSwitching(@UserIdInt int fromUserId, @UserIdInt int toUserId) { 2190 if (DBG) { 2191 Slogf.i(TAG, "onUserSwitching(from=%d, to=%d)", fromUserId, toUserId); 2192 } 2193 TimingsTraceLog t = new TimingsTraceLog(TAG, TraceHelper.TRACE_TAG_CAR_SERVICE); 2194 t.traceBegin("onUserSwitching-" + toUserId); 2195 2196 notifyLegacyUserSwitch(fromUserId, toUserId); 2197 2198 mInitialUserSetter.setLastActiveUser(toUserId); 2199 2200 t.traceEnd(); 2201 } 2202 notifyLegacyUserSwitch(@serIdInt int fromUserId, @UserIdInt int toUserId)2203 private void notifyLegacyUserSwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) { 2204 if (DBG) { 2205 Slogf.d(TAG, "notifyLegacyUserSwitch(%d, %d): mUserIdForUserSwitchInProcess=%d", 2206 fromUserId, toUserId, mUserIdForUserSwitchInProcess); 2207 } 2208 synchronized (mLockUser) { 2209 if (mUserIdForUserSwitchInProcess != USER_NULL) { 2210 if (mUserIdForUserSwitchInProcess == toUserId) { 2211 if (DBG) { 2212 Slogf.d(TAG, "Ignoring, not legacy"); 2213 } 2214 return; 2215 } 2216 if (DBG) { 2217 Slogf.d(TAG, "Resetting mUserIdForUserSwitchInProcess"); 2218 } 2219 mUserIdForUserSwitchInProcess = USER_NULL; 2220 mRequestIdForUserSwitchInProcess = 0; 2221 } 2222 } 2223 2224 sendUserSwitchUiCallback(toUserId); 2225 2226 // Switch HAL users if user switch is not requested by CarUserService 2227 notifyHalLegacySwitch(fromUserId, toUserId); 2228 } 2229 notifyHalLegacySwitch(@serIdInt int fromUserId, @UserIdInt int toUserId)2230 private void notifyHalLegacySwitch(@UserIdInt int fromUserId, @UserIdInt int toUserId) { 2231 if (!isUserHalSupported()) { 2232 if (DBG) { 2233 Slogf.d(TAG, "notifyHalLegacySwitch(): not calling UserHal (not supported)"); 2234 } 2235 return; 2236 } 2237 2238 // switch HAL user 2239 UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUserManager, mUserHandleHelper, 2240 fromUserId); 2241 SwitchUserRequest request = createUserSwitchRequest(toUserId, usersInfo); 2242 mHal.legacyUserSwitch(request); 2243 } 2244 2245 /** 2246 * Runs the given runnable when user 0 is unlocked. If user 0 is already unlocked, it is 2247 * run inside this call. 2248 * 2249 * @param r Runnable to run. 2250 */ runOnUser0Unlock(@onNull Runnable r)2251 public void runOnUser0Unlock(@NonNull Runnable r) { 2252 Objects.requireNonNull(r, "runnable cannot be null"); 2253 boolean runNow = false; 2254 synchronized (mLockUser) { 2255 if (mUser0Unlocked) { 2256 runNow = true; 2257 } else { 2258 mUser0UnlockTasks.add(r); 2259 } 2260 } 2261 if (runNow) { 2262 r.run(); 2263 } 2264 } 2265 2266 @VisibleForTesting 2267 @NonNull getBackgroundUsersToRestart()2268 ArrayList<Integer> getBackgroundUsersToRestart() { 2269 ArrayList<Integer> backgroundUsersToRestart = null; 2270 synchronized (mLockUser) { 2271 backgroundUsersToRestart = new ArrayList<>(mBackgroundUsersToRestart); 2272 } 2273 return backgroundUsersToRestart; 2274 } 2275 setSystemUserRestrictions()2276 private void setSystemUserRestrictions() { 2277 // Disable Location service for system user. 2278 LocationManager locationManager = 2279 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 2280 locationManager.setLocationEnabledForUser( 2281 /* enabled= */ false, UserHandle.SYSTEM); 2282 locationManager.setAdasGnssLocationEnabled(false); 2283 } 2284 checkInteractAcrossUsersPermission(String message)2285 private void checkInteractAcrossUsersPermission(String message) { 2286 checkHasAtLeastOnePermissionGranted(mContext, message, 2287 android.Manifest.permission.INTERACT_ACROSS_USERS, 2288 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); 2289 } 2290 2291 /** 2292 * Manages the required number of pre-created users. 2293 */ 2294 @Override updatePreCreatedUsers()2295 public void updatePreCreatedUsers() { 2296 checkManageOrCreateUsersPermission("preCreateUsers"); 2297 preCreateUsersInternal(/* waitTimeMs= */ DEFAULT_PRE_CREATION_DELAY_MS); 2298 } 2299 preCreateUsersInternal(int waitTimeMs)2300 private void preCreateUsersInternal(int waitTimeMs) { 2301 mHandler.postDelayed(() -> mUserPreCreator.managePreCreatedUsers(), waitTimeMs); 2302 } 2303 2304 // TODO(b/167698977): members below were copied from UserManagerService; it would be better to 2305 // move them to some internal android.os class instead. 2306 private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION = 2307 UserManagerHelper.FLAG_MANAGED_PROFILE 2308 | UserManagerHelper.FLAG_PROFILE 2309 | UserManagerHelper.FLAG_EPHEMERAL 2310 | UserManagerHelper.FLAG_RESTRICTED 2311 | UserManagerHelper.FLAG_GUEST 2312 | UserManagerHelper.FLAG_DEMO 2313 | UserManagerHelper.FLAG_FULL; 2314 checkManageUsersPermission(String message)2315 static void checkManageUsersPermission(String message) { 2316 if (!hasManageUsersPermission()) { 2317 throw new SecurityException("You need " + MANAGE_USERS + " permission to: " + message); 2318 } 2319 } 2320 checkManageOrCreateUsersPermission(String message)2321 private static void checkManageOrCreateUsersPermission(String message) { 2322 if (!hasManageOrCreateUsersPermission()) { 2323 throw new SecurityException( 2324 "You either need " + MANAGE_USERS + " or " + CREATE_USERS + " permission to: " 2325 + message); 2326 } 2327 } 2328 checkManageOrCreateUsersPermission(int creationFlags)2329 private static void checkManageOrCreateUsersPermission(int creationFlags) { 2330 if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) { 2331 if (!hasManageOrCreateUsersPermission()) { 2332 throw new SecurityException("You either need " + MANAGE_USERS + " or " 2333 + CREATE_USERS + "permission to create a user with flags " 2334 + creationFlags); 2335 } 2336 } else if (!hasManageUsersPermission()) { 2337 throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user" 2338 + " with flags " + creationFlags); 2339 } 2340 } 2341 hasManageUsersPermission()2342 private static boolean hasManageUsersPermission() { 2343 final int callingUid = Binder.getCallingUid(); 2344 return isSameApp(callingUid, Process.SYSTEM_UID) 2345 || callingUid == Process.ROOT_UID 2346 || hasPermissionGranted(MANAGE_USERS, callingUid); 2347 } 2348 hasManageUsersOrPermission(String alternativePermission)2349 private static boolean hasManageUsersOrPermission(String alternativePermission) { 2350 final int callingUid = Binder.getCallingUid(); 2351 return isSameApp(callingUid, Process.SYSTEM_UID) 2352 || callingUid == Process.ROOT_UID 2353 || hasPermissionGranted(MANAGE_USERS, callingUid) 2354 || hasPermissionGranted(alternativePermission, callingUid); 2355 } 2356 isSameApp(int uid1, int uid2)2357 private static boolean isSameApp(int uid1, int uid2) { 2358 return UserHandle.getAppId(uid1) == UserHandle.getAppId(uid2); 2359 } 2360 hasManageOrCreateUsersPermission()2361 private static boolean hasManageOrCreateUsersPermission() { 2362 return hasManageUsersOrPermission(CREATE_USERS); 2363 } 2364 hasPermissionGranted(String permission, int uid)2365 private static boolean hasPermissionGranted(String permission, int uid) { 2366 return ActivityManagerHelper.checkComponentPermission(permission, uid, /* owningUid= */ -1, 2367 /* exported= */ true) == PackageManager.PERMISSION_GRANTED; 2368 } 2369 userOperationErrorToString(int error)2370 private static String userOperationErrorToString(int error) { 2371 return DebugUtils.constantToString(UserManager.class, "USER_OPERATION_", error); 2372 } 2373 } 2374