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