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