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