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