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