• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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