• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 android.car.user;
18 
19 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
20 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
21 import static android.os.Process.myUid;
22 
23 import static com.android.car.internal.util.FunctionalUtils.getLambdaName;
24 
25 import android.annotation.CallbackExecutor;
26 import android.annotation.FlaggedApi;
27 import android.annotation.IntDef;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.annotation.RequiresPermission;
31 import android.annotation.SystemApi;
32 import android.annotation.TestApi;
33 import android.annotation.UserIdInt;
34 import android.car.CarManagerBase;
35 import android.car.ICarResultReceiver;
36 import android.car.ICarUserService;
37 import android.car.ResultCallback;
38 import android.car.SyncResultCallback;
39 import android.car.builtin.os.UserManagerHelper;
40 import android.car.builtin.util.EventLogHelper;
41 import android.car.drivingstate.CarUxRestrictions;
42 import android.car.feature.Flags;
43 import android.car.util.concurrent.AndroidAsyncFuture;
44 import android.car.util.concurrent.AndroidFuture;
45 import android.car.util.concurrent.AsyncFuture;
46 import android.os.Bundle;
47 import android.os.IBinder;
48 import android.os.RemoteException;
49 import android.os.UserHandle;
50 import android.os.UserManager;
51 import android.util.ArrayMap;
52 import android.util.Dumpable;
53 import android.util.Log;
54 import android.util.Pair;
55 import android.util.Slog;
56 
57 import com.android.car.internal.ICarBase;
58 import com.android.car.internal.ResultCallbackImpl;
59 import com.android.car.internal.common.CommonConstants;
60 import com.android.car.internal.common.CommonConstants.UserLifecycleEventType;
61 import com.android.car.internal.common.UserHelperLite;
62 import com.android.car.internal.os.CarSystemProperties;
63 import com.android.car.internal.util.ArrayUtils;
64 import com.android.internal.annotations.GuardedBy;
65 import com.android.internal.annotations.VisibleForTesting;
66 import com.android.internal.util.Preconditions;
67 
68 import java.io.PrintWriter;
69 import java.lang.annotation.Retention;
70 import java.lang.annotation.RetentionPolicy;
71 import java.util.ArrayList;
72 import java.util.Arrays;
73 import java.util.List;
74 import java.util.Objects;
75 import java.util.concurrent.Executor;
76 import java.util.concurrent.TimeUnit;
77 import java.util.concurrent.TimeoutException;
78 import java.util.stream.Collectors;
79 
80 /**
81  * API to manage users related to car.
82  *
83  * @hide
84  */
85 @SystemApi
86 public final class CarUserManager extends CarManagerBase {
87 
88     /** @hide */
89     public static final String TAG = CarUserManager.class.getSimpleName();
90 
91     private static final int HAL_TIMEOUT_MS = CarSystemProperties.getUserHalTimeout().orElse(5_000);
92     private static final int USER_CALL_TIMEOUT_MS = 60_000;
93 
94     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
95     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
96 
97     /**
98      * {@link UserLifecycleEvent} called when the user is starting, for components to initialize
99      * any per-user state they maintain for running users.
100      *
101      * @hide
102      */
103     @SystemApi
104     public static final int USER_LIFECYCLE_EVENT_TYPE_STARTING =
105             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STARTING;
106 
107     /**
108      * {@link UserLifecycleEvent} called when switching to a different foreground user, for
109      * components that have special behavior for whichever user is currently in the foreground.
110      *
111      * <p>This is called before any application processes are aware of the new user.
112      *
113      * <p>Notice that internal system services might not have handled user switching yet, so be
114      * careful with interaction with them.
115      *
116      * @hide
117      */
118     @SystemApi
119     public static final int USER_LIFECYCLE_EVENT_TYPE_SWITCHING =
120             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_SWITCHING;
121 
122     /**
123      * {@link UserLifecycleEvent} called when an existing user is in the process of being unlocked.
124      *
125      * <p>This means the credential-encrypted storage for that user is now available, and
126      * encryption-aware component filtering is no longer in effect.
127      *
128      * <p>Notice that internal system services might not have handled unlock yet, so most components
129      * should ignore this callback and rely on {@link #USER_LIFECYCLE_EVENT_TYPE_UNLOCKED} instead.
130      *
131      * @hide
132      */
133     @SystemApi
134     public static final int USER_LIFECYCLE_EVENT_TYPE_UNLOCKING =
135             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_UNLOCKING;
136 
137     /**
138      * {@link UserLifecycleEvent} called after an existing user is unlocked.
139      *
140      * @hide
141      */
142     @SystemApi
143     public static final int USER_LIFECYCLE_EVENT_TYPE_UNLOCKED =
144             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_UNLOCKED;
145 
146     /**
147      * {@link UserLifecycleEvent} called after an existing user is unlocked for components to
148      * perform non-urgent tasks for user unlocked.
149      *
150      * <p>Note: This event type is intended only for internal system services. Application listeners
151      * should not use this event type and will not receive any events of this type.
152      *
153      * @hide
154      */
155     public static final int USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED =
156             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED;
157 
158     /**
159      * {@link UserLifecycleEvent} called when an existing user is stopping, for components to
160      * finalize any per-user state they maintain for running users.
161      *
162      * <p>This is called prior to sending the {@code SHUTDOWN} broadcast to the user; it is a good
163      * place to stop making use of any resources of that user (such as binding to a service running
164      * in the user).
165      *
166      * <p><b>Note:</b> this is the last callback where the callee may access the target user's CE
167      * storage.
168      *
169      * @hide
170      */
171     @SystemApi
172     public static final int USER_LIFECYCLE_EVENT_TYPE_STOPPING =
173             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STOPPING;
174 
175     /**
176      * {@link UserLifecycleEvent} called after an existing user is stopped.
177      *
178      * <p>This is called after all application process teardown of the user is complete.
179      *
180      * @hide
181      */
182     @SystemApi
183     public static final int USER_LIFECYCLE_EVENT_TYPE_STOPPED =
184             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_STOPPED;
185 
186     /**
187      * {@link UserLifecycleEvent} called after an existing user is created.
188      *
189      * @hide
190      */
191     @SystemApi
192     public static final int USER_LIFECYCLE_EVENT_TYPE_CREATED =
193             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_CREATED;
194 
195     /**
196      * {@link UserLifecycleEvent} called after an existing user is removed.
197      *
198      * @hide
199      */
200     @SystemApi
201     public static final int USER_LIFECYCLE_EVENT_TYPE_REMOVED =
202             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_REMOVED;
203 
204     /**
205      * {@link UserLifecycleEvent} called after an existing user becomes visible.
206      *
207      * @hide
208      */
209     @SystemApi
210     public static final int USER_LIFECYCLE_EVENT_TYPE_VISIBLE =
211             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_VISIBLE;
212 
213     /**
214      * {@link UserLifecycleEvent} called after an existing user becomes invisible.
215      *
216      * @hide
217      */
218     @SystemApi
219     public static final int USER_LIFECYCLE_EVENT_TYPE_INVISIBLE =
220             CommonConstants.USER_LIFECYCLE_EVENT_TYPE_INVISIBLE;
221 
222     /** @hide */
223     public static final String BUNDLE_PARAM_ACTION = "action";
224     /** @hide */
225     public static final String BUNDLE_PARAM_PREVIOUS_USER_ID = "previous_user";
226 
227     /**
228      * {@link UserIdentificationAssociationType} for key fob.
229      *
230      * @hide
231      */
232     public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_KEY_FOB = 1;
233 
234     /**
235      * {@link UserIdentificationAssociationType} for custom type 1.
236      *
237      * @hide
238      */
239     public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_1 = 101;
240 
241     /**
242      * {@link UserIdentificationAssociationType} for custom type 2.
243      *
244      * @hide
245      */
246     public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_2 = 102;
247 
248     /**
249      * {@link UserIdentificationAssociationType} for custom type 3.
250      *
251      * @hide
252      */
253     public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_3 = 103;
254 
255     /**
256      * {@link UserIdentificationAssociationType} for custom type 4.
257      *
258      * @hide
259      */
260     public static final int USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_4 = 104;
261 
262     /**
263      *  User HAL's user identification association types
264      *
265      * @hide
266      */
267     @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_TYPE_" }, value = {
268             USER_IDENTIFICATION_ASSOCIATION_TYPE_KEY_FOB,
269             USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_1,
270             USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_2,
271             USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_3,
272             USER_IDENTIFICATION_ASSOCIATION_TYPE_CUSTOM_4,
273     })
274     @Retention(RetentionPolicy.SOURCE)
275     public @interface UserIdentificationAssociationType{}
276 
277     /**
278      * {@link UserIdentificationAssociationSetValue} to associate the identification type with the
279      * current foreground Android user.
280      *
281      * @hide
282      */
283     public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_ASSOCIATE_CURRENT_USER = 1;
284 
285     /**
286      * {@link UserIdentificationAssociationSetValue} to disassociate the identification type from
287      * the current foreground Android user.
288      *
289      * @hide
290      */
291     public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_CURRENT_USER = 2;
292 
293     /**
294      * {@link UserIdentificationAssociationSetValue} to disassociate the identification type from
295      * all Android users.
296      *
297      * @hide
298      */
299     public static final int USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_ALL_USERS = 3;
300 
301     /**
302      * User HAL's user identification association types
303      *
304      * @hide
305      */
306     @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_" }, value = {
307             USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_ASSOCIATE_CURRENT_USER,
308             USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_CURRENT_USER,
309             USER_IDENTIFICATION_ASSOCIATION_SET_VALUE_DISASSOCIATE_ALL_USERS,
310     })
311     @Retention(RetentionPolicy.SOURCE)
312     public @interface UserIdentificationAssociationSetValue{}
313 
314     /**
315      * {@link UserIdentificationAssociationValue} when the status of an association could not be
316      * determined.
317      *
318      * @hide
319      */
320     public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_UNKNOWN = 1;
321 
322     /**
323      * {@link UserIdentificationAssociationValue} when the identification type is associated with
324      * the current foreground Android user.
325      *
326      * @hide
327      */
328     public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATE_CURRENT_USER = 2;
329 
330     /**
331      * {@link UserIdentificationAssociationValue} when the identification type is associated with
332      * another Android user.
333      *
334      * @hide
335      */
336     public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATED_ANOTHER_USER = 3;
337 
338     /**
339      * {@link UserIdentificationAssociationValue} when the identification type is not associated
340      * with any Android user.
341      *
342      * @hide
343      */
344     public static final int USER_IDENTIFICATION_ASSOCIATION_VALUE_NOT_ASSOCIATED_ANY_USER = 4;
345 
346     /**
347      * User HAL's user identification association types
348      *
349      * @hide
350      */
351     @IntDef(prefix = { "USER_IDENTIFICATION_ASSOCIATION_VALUE_" }, value = {
352             USER_IDENTIFICATION_ASSOCIATION_VALUE_UNKNOWN,
353             USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATE_CURRENT_USER,
354             USER_IDENTIFICATION_ASSOCIATION_VALUE_ASSOCIATED_ANOTHER_USER,
355             USER_IDENTIFICATION_ASSOCIATION_VALUE_NOT_ASSOCIATED_ANY_USER,
356     })
357     @Retention(RetentionPolicy.SOURCE)
358     public @interface UserIdentificationAssociationValue{}
359 
360     private final Object mLock = new Object();
361 
362     private final ICarUserService mService;
363     private final UserManager mUserManager;
364     private final boolean mIsHeadlessSystemUserMode;
365 
366     /**
367      * Map of listeners registers by the app.
368      */
369     @Nullable
370     @GuardedBy("mLock")
371     private ArrayMap<UserLifecycleListener, Pair<UserLifecycleEventFilter, Executor>> mListeners;
372 
373     /**
374      * Receiver used to receive user-lifecycle callbacks from the service.
375      */
376     @Nullable
377     @GuardedBy("mLock")
378     private LifecycleResultReceiver mReceiver;
379 
380     private final Dumper mDumper;
381 
382     /**
383      * Logs the number of received events so it's shown on {@code Dumper.dump()}.
384      */
385     private int mNumberReceivedEvents;
386 
387     /**
388      * Logs the received events so they're shown on {@code Dumper.dump()}.
389      *
390      * <p><b>Note</b>: these events are only logged when {@link #VERBOSE} is {@code true}.
391      */
392     @Nullable
393     private List<UserLifecycleEvent> mEvents;
394 
395     /**
396      * @hide
397      */
CarUserManager(@onNull ICarBase car, @NonNull IBinder service)398     public CarUserManager(@NonNull ICarBase car, @NonNull IBinder service) {
399         this(car, ICarUserService.Stub.asInterface(service),
400                 car.getContext().getSystemService(UserManager.class),
401                 UserManager.isHeadlessSystemUserMode());
402     }
403 
404     /**
405      * @hide
406      */
407     @VisibleForTesting
CarUserManager(@onNull ICarBase car, @NonNull ICarUserService service, @NonNull UserManager userManager, boolean isHeadlessSystemUserMode)408     public CarUserManager(@NonNull ICarBase car, @NonNull ICarUserService service,
409             @NonNull UserManager userManager, boolean isHeadlessSystemUserMode) {
410         super(car);
411 
412         mDumper = addDumpable(car.getContext(), () -> new Dumper());
413         Slog.d(TAG, "CarUserManager(): DBG= " + DBG + ", mDumper=" + mDumper);
414 
415         mService = service;
416         mUserManager = userManager;
417         mIsHeadlessSystemUserMode = isHeadlessSystemUserMode;
418     }
419 
420     /**
421      * Starts the specified user.
422      *
423      * @hide
424      */
425     @SystemApi
426     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
427             android.Manifest.permission.INTERACT_ACROSS_USERS})
startUser(@onNull UserStartRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserStartResponse> callback)428     public void startUser(@NonNull UserStartRequest request,
429             @NonNull @CallbackExecutor Executor executor,
430             @NonNull ResultCallback<UserStartResponse> callback) {
431         int uid = myUid();
432         int userId = request.getUserHandle().getIdentifier();
433         int displayId = request.getDisplayId();
434         EventLogHelper.writeCarUserManagerStartUserReq(uid, userId, displayId);
435         try {
436             ResultCallbackImpl<UserStartResponse> callbackImpl = new ResultCallbackImpl<>(
437                     executor, callback) {
438                 @Override
439                 protected void onCompleted(UserStartResponse response) {
440                     EventLogHelper.writeCarUserManagerStartUserResp(uid, userId, displayId,
441                             response != null ? response.getStatus()
442                                     : UserStartResponse.STATUS_ANDROID_FAILURE);
443                     super.onCompleted(response);
444                 }
445             };
446             mService.startUser(request, callbackImpl);
447         } catch (SecurityException e) {
448             Slog.e(TAG, "startUser(userId=" + userId + ", displayId=" + displayId + ")", e);
449             throw e;
450         } catch (RemoteException | RuntimeException e) {
451             UserStartResponse response = handleExceptionFromCarService(e,
452                     new UserStartResponse(UserStartResponse.STATUS_ANDROID_FAILURE));
453             callback.onResult(response);
454         }
455     }
456 
457     /**
458      * Stops the specified user.
459      *
460      * @hide
461      */
462     @SystemApi
463     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
464             android.Manifest.permission.INTERACT_ACROSS_USERS})
stopUser(@onNull UserStopRequest request, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserStopResponse> callback)465     public void stopUser(@NonNull UserStopRequest request,
466             @NonNull @CallbackExecutor Executor executor,
467             @NonNull ResultCallback<UserStopResponse> callback) {
468         int uid = myUid();
469         int userId = request.getUserHandle().getIdentifier();
470         EventLogHelper.writeCarUserManagerStopUserReq(uid, userId);
471         try {
472             ResultCallbackImpl<UserStopResponse> callbackImpl = new ResultCallbackImpl<>(
473                     executor, callback) {
474                 @Override
475                 protected void onCompleted(UserStopResponse response) {
476                     EventLogHelper.writeCarUserManagerStopUserResp(uid, userId,
477                             response != null ? response.getStatus()
478                                     : UserStopResponse.STATUS_ANDROID_FAILURE);
479                     super.onCompleted(response);
480                 }
481             };
482             mService.stopUser(request, callbackImpl);
483         } catch (SecurityException e) {
484             Slog.e(TAG, "stopUser(userId=" + userId + ")", e);
485             throw e;
486         } catch (RemoteException | RuntimeException e) {
487             UserStopResponse response = handleExceptionFromCarService(e,
488                     new UserStopResponse(UserStopResponse.STATUS_ANDROID_FAILURE));
489             callback.onResult(response);
490         }
491     }
492 
493     /**
494      * Switches the foreground user to the given user. Ignores UX Restrictions regarding user
495      * switching or {@link CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP}.
496      *
497      * @param userSwitchRequest contains target user.
498      * @param executor to execute the callback.
499      * @param callback called with the {@code UserSwitchResult}
500      *
501      * @hide
502      */
503     @FlaggedApi(Flags.FLAG_SWITCH_USER_IGNORING_UXR)
504     @SystemApi
505     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
506             android.Manifest.permission.CREATE_USERS})
switchUserIgnoringUxRestriction(@onNull UserSwitchRequest userSwitchRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserSwitchResult> callback)507     public void switchUserIgnoringUxRestriction(@NonNull UserSwitchRequest userSwitchRequest,
508             @NonNull @CallbackExecutor Executor executor,
509             @NonNull ResultCallback<UserSwitchResult> callback) {
510         switchUser(userSwitchRequest, executor, callback, /* ignoreUxRestriction=*/ true);
511     }
512 
513     /**
514      * Switches the foreground user to the given user.
515      *
516      * @param userSwitchRequest contains target user.
517      * @param executor to execute the callback.
518      * @param callback called with the {@code UserSwitchResult}
519      *
520      * @hide
521      */
522     @SystemApi
523     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
524             android.Manifest.permission.CREATE_USERS})
switchUser(@onNull UserSwitchRequest userSwitchRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserSwitchResult> callback)525     public void switchUser(@NonNull UserSwitchRequest userSwitchRequest,
526             @NonNull @CallbackExecutor Executor executor,
527             @NonNull ResultCallback<UserSwitchResult> callback) {
528         switchUser(userSwitchRequest, executor, callback, /* ignoreUxRestriction=*/ false);
529     }
530 
531 
switchUser(@onNull UserSwitchRequest userSwitchRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserSwitchResult> callback, boolean ignoreUxRestriction)532     private void switchUser(@NonNull UserSwitchRequest userSwitchRequest,
533             @NonNull @CallbackExecutor Executor executor,
534             @NonNull ResultCallback<UserSwitchResult> callback, boolean ignoreUxRestriction) {
535         if (DBG) {
536             Slog.d(TAG, "switchuser(): userHandle=" + userSwitchRequest.getUserHandle()
537                     + ", ignoreUxRestriction=" + ignoreUxRestriction);
538         }
539         int uid = myUid();
540         int targetUserId = userSwitchRequest.getUserHandle().getIdentifier();
541 
542         try {
543             ResultCallbackImpl<UserSwitchResult> resultCallbackImpl = new ResultCallbackImpl<>(
544                     executor, callback) {
545                 @Override
546                 protected void onCompleted(UserSwitchResult result) {
547                     if (result == null) {
548                         EventLogHelper.writeCarUserManagerSwitchUserResp(uid,
549                                 UserSwitchResult.STATUS_ANDROID_FAILURE, /* errorMessage=*/ null);
550                     } else {
551                         EventLogHelper.writeCarUserManagerSwitchUserResp(uid, result.getStatus(),
552                                 result.getErrorMessage());
553                     }
554                     super.onCompleted(result);
555                 }
556             };
557             EventLogHelper.writeCarUserManagerSwitchUserReq(uid, targetUserId);
558             mService.switchUser(targetUserId, HAL_TIMEOUT_MS, resultCallbackImpl,
559                     ignoreUxRestriction);
560         } catch (SecurityException e) {
561             Slog.w(TAG, "switchUser(" + targetUserId + ") failed: " + e);
562             throw e;
563         } catch (RemoteException | RuntimeException e) {
564             UserSwitchResult result = handleExceptionFromCarService(e,
565                     new UserSwitchResult(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE, null));
566             callback.onResult(result);
567         }
568     }
569 
570     /**
571      * Switches the foreground user to the given target user.
572      *
573      * @hide
574      * @deprecated Use {@link #switchUser(UserSwitchRequest, Executor, ResultCallback)} instead.
575      */
576     @TestApi
577     @Deprecated
578     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
579             android.Manifest.permission.CREATE_USERS})
switchUser(@serIdInt int targetUserId)580     public AsyncFuture<UserSwitchResult> switchUser(@UserIdInt int targetUserId) {
581         UserSwitchRequest userSwitchRequest = new UserSwitchRequest.Builder(
582                 UserHandle.of(targetUserId)).build();
583         AndroidFuture<UserSwitchResult> future = new AndroidFuture<>();
584         switchUser(userSwitchRequest, Runnable::run, future::complete);
585         return new AndroidAsyncFuture<>(future);
586     }
587 
588     /**
589      * Logouts the current user (if it was switched to by a device admin).
590      *
591      * @hide
592      */
593     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
594             android.Manifest.permission.CREATE_USERS})
logoutUser()595     public AsyncFuture<UserSwitchResult> logoutUser() {
596         int uid = myUid();
597         try {
598             AndroidFuture<UserSwitchResult> future = new AndroidFuture<>();
599             ResultCallbackImpl<UserSwitchResult> resultCallbackImpl = new ResultCallbackImpl<>(
600                     Runnable::run, new SyncResultCallback<>()) {
601                 @Override
602                 protected void onCompleted(UserSwitchResult result) {
603                     if (result == null) {
604                         EventLogHelper.writeCarUserManagerLogoutUserResp(uid,
605                                 UserSwitchResult.STATUS_ANDROID_FAILURE, /* errorMessage=*/ null);
606                     } else {
607                         EventLogHelper.writeCarUserManagerLogoutUserResp(uid, result.getStatus(),
608                                 result.getErrorMessage());
609                     }
610                     future.complete(result);
611                     super.onCompleted(result);
612                 }
613             };
614             EventLogHelper.writeCarUserManagerLogoutUserReq(uid);
615             mService.logoutUser(HAL_TIMEOUT_MS, resultCallbackImpl);
616             return new AndroidAsyncFuture<>(future);
617         } catch (SecurityException e) {
618             throw e;
619         } catch (RemoteException | RuntimeException e) {
620             AsyncFuture<UserSwitchResult> future =
621                     newSwitchResultForFailure(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE);
622             return handleExceptionFromCarService(e, future);
623         }
624     }
625 
newSwitchResultForFailure( @serSwitchResult.Status int status)626     private AndroidAsyncFuture<UserSwitchResult> newSwitchResultForFailure(
627             @UserSwitchResult.Status int status) {
628         AndroidFuture<UserSwitchResult> future = new AndroidFuture<>();
629         future.complete(new UserSwitchResult(status, null));
630         return new AndroidAsyncFuture<>(future);
631     }
632 
633     /**
634      * Creates a new guest Android user.
635      *
636      * @hide
637      * @deprecated Use {@link #createUser(UserCreationRequest, Executor, ResultCallback)} instead.
638      */
639     @Deprecated
640     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
641             android.Manifest.permission.CREATE_USERS})
createGuest(@ullable String name)642     public AsyncFuture<UserCreationResult> createGuest(@Nullable String name) {
643         AndroidFuture<UserCreationResult> future = new AndroidFuture<>();
644         UserCreationRequest.Builder userCreationRequestBuilder = new UserCreationRequest.Builder();
645         if (name != null) {
646             userCreationRequestBuilder.setName(name);
647         }
648         createUser(userCreationRequestBuilder.setGuest().build(), Runnable::run, future::complete);
649         return new AndroidAsyncFuture<>(future);
650     }
651 
652     /**
653      * Creates a new Android user.
654      *
655      * @hide
656      * @deprecated Use {@link #createUser(UserCreationRequest, Executor, ResultCallback)} instead.
657      */
658     @Deprecated
659     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
660             android.Manifest.permission.CREATE_USERS})
createUser(@ullable String name, int flags)661     public AsyncFuture<UserCreationResult> createUser(@Nullable String name,
662             int flags) {
663         AndroidFuture<UserCreationResult> future = new AndroidFuture<>();
664         UserCreationRequest.Builder userCreationRequestBuilder = new UserCreationRequest.Builder();
665         if (name != null) {
666             userCreationRequestBuilder.setName(name);
667         }
668 
669         if ((flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) {
670             userCreationRequestBuilder.setAdmin();
671         }
672 
673         if ((flags & UserManagerHelper.FLAG_EPHEMERAL) == UserManagerHelper.FLAG_EPHEMERAL) {
674             userCreationRequestBuilder.setEphemeral();
675         }
676 
677         createUser(userCreationRequestBuilder.build(), Runnable::run, future::complete);
678         return new AndroidAsyncFuture<>(future);
679     }
680 
681     /**
682      * Creates a new Android user.
683      *
684      * @param userCreationRequest contains new user information
685      * @param executor to execute the callback.
686      * @param callback called with the {code UserCreationResult}
687      * @hide
688      */
689     @SystemApi
690     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
691             android.Manifest.permission.CREATE_USERS})
createUser(@onNull UserCreationRequest userCreationRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserCreationResult> callback)692     public void createUser(@NonNull UserCreationRequest userCreationRequest,
693             @NonNull @CallbackExecutor Executor executor,
694             @NonNull ResultCallback<UserCreationResult> callback) {
695         Objects.requireNonNull(userCreationRequest, "userCreationRequest cannot be null");
696         Objects.requireNonNull(executor, "executor cannot be null");
697         Objects.requireNonNull(callback, "callback cannot be null");
698         int uid = myUid();
699         try {
700             ResultCallbackImpl<UserCreationResult> resultCallbackImpl =
701                     new ResultCallbackImpl<UserCreationResult>(
702                     executor, callback) {
703                 @Override
704                 protected void onCompleted(UserCreationResult result) {
705                     if (result == null) {
706                         EventLogHelper.writeCarUserManagerCreateUserResp(uid,
707                                 UserCreationResult.STATUS_ANDROID_FAILURE, /* errorMessage=*/ null);
708                     } else {
709                         EventLogHelper.writeCarUserManagerCreateUserResp(uid, result.getStatus(),
710                                 result.getErrorMessage());
711                     }
712                     super.onCompleted(result);
713                 }
714             };
715             String name = userCreationRequest.getName();
716             String userType = userCreationRequest.isGuest() ? UserManager.USER_TYPE_FULL_GUEST
717                     : UserManager.USER_TYPE_FULL_SECONDARY;
718             int flags = 0;
719             flags |= userCreationRequest.isAdmin() ? UserManagerHelper.FLAG_ADMIN : 0;
720             flags |= userCreationRequest.isEphemeral() ? UserManagerHelper.FLAG_EPHEMERAL : 0;
721 
722             EventLogHelper.writeCarUserManagerCreateUserReq(uid,
723                     UserHelperLite.safeName(name), userType, flags);
724             mService.createUser(userCreationRequest, HAL_TIMEOUT_MS, resultCallbackImpl);
725         } catch (SecurityException e) {
726             throw e;
727         } catch (RemoteException | RuntimeException e) {
728             callback.onResult(
729                     new UserCreationResult(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE));
730             handleExceptionFromCarService(e, null);
731         }
732     }
733 
734     /**
735      * Updates pre-created users.
736      *
737      * @deprecated Pre-created users are no longer supported.
738      *             This method is no-op and will be removed soon.
739      *
740      * @hide
741      */
742     @Deprecated
743     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
744             android.Manifest.permission.CREATE_USERS})
updatePreCreatedUsers()745     public void updatePreCreatedUsers() {
746         Slog.w(TAG, "updatePreCreatedUsers(): This method should not be called."
747                 + " Pre-created users are no longer supported.");
748     }
749 
750 
751     /**
752      * Removes the given user.
753      *
754      * @param userRemovalRequest contains user to be removed.
755      * @param executor to execute the callback.
756      * @param callback called with the {code UserRemovalResult}
757      *
758      * @hide
759      */
760     @SystemApi
761     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
762             android.Manifest.permission.CREATE_USERS})
removeUser(@onNull UserRemovalRequest userRemovalRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserRemovalResult> callback)763     public void removeUser(@NonNull UserRemovalRequest userRemovalRequest,
764             @NonNull @CallbackExecutor Executor executor,
765             @NonNull ResultCallback<UserRemovalResult> callback) {
766         int uid = myUid();
767         EventLogHelper.writeCarUserManagerRemoveUserReq(uid,
768                 userRemovalRequest.getUserHandle().getIdentifier());
769         try {
770             ResultCallbackImpl<UserRemovalResult> resultCallbackImpl = new ResultCallbackImpl<>(
771                     executor, callback) {
772                 @Override
773                 protected void onCompleted(UserRemovalResult result) {
774                     EventLogHelper.writeCarUserManagerRemoveUserResp(uid,
775                             result != null ? result.getStatus()
776                                     : UserRemovalResult.STATUS_ANDROID_FAILURE);
777                     super.onCompleted(result);
778                 }
779             };
780             mService.removeUser(userRemovalRequest.getUserHandle().getIdentifier(),
781                     resultCallbackImpl);
782         } catch (SecurityException e) {
783             Slog.e(TAG, "CarUserManager removeUser", e);
784             throw e;
785         } catch (RemoteException | RuntimeException e) {
786             UserRemovalResult result = handleExceptionFromCarService(e,
787                     new UserRemovalResult(UserRemovalResult.STATUS_ANDROID_FAILURE));
788             callback.onResult(result);
789         }
790     }
791 
792     /**
793      * Removes the given user.
794      *
795      * @param userId identification of the user to be removed.
796      *
797      * @return whether the user was successfully removed.
798      *
799      * @hide
800      *
801      * @deprecated use {@link #removeUser(UserRemovalRequest, Executor, ResultCallback)} instead.
802      * It will be marked removed in {@code V} and hard removed in {@code X}.
803      */
804     @Deprecated
805     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
806             android.Manifest.permission.CREATE_USERS})
807     @NonNull
removeUser(@serIdInt int userId)808     public UserRemovalResult removeUser(@UserIdInt int userId) {
809         UserRemovalRequest userRemovalRequest = new UserRemovalRequest.Builder(
810                 UserHandle.of(userId)).build();
811         SyncResultCallback<UserRemovalResult> userRemovalResultCallback =
812                 new SyncResultCallback<>();
813 
814         removeUser(userRemovalRequest, Runnable::run, userRemovalResultCallback);
815 
816         UserRemovalResult userRemovalResult = new UserRemovalResult(
817                 UserRemovalResult.STATUS_ANDROID_FAILURE);
818 
819         try {
820             userRemovalResult = userRemovalResultCallback.get(USER_CALL_TIMEOUT_MS,
821                     TimeUnit.MILLISECONDS);
822         } catch (TimeoutException e) {
823             Slog.e(TAG, "CarUserManager removeUser(" + userId + "): ", e);
824         } catch (InterruptedException e) {
825             Thread.currentThread().interrupt();
826             Slog.e(TAG, "CarUserManager removeUser(" + userId + "): ", e);
827         }
828 
829         return userRemovalResult;
830     }
831 
832     /**
833      * Adds a listener for {@link UserLifecycleEvent user lifecycle events}.
834      *
835      * @throws IllegalStateException if the listener was already added.
836      *
837      * @hide
838      */
839     @SystemApi
840     @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleListener listener)841     public void addListener(@NonNull @CallbackExecutor Executor executor,
842             @NonNull UserLifecycleListener listener) {
843         addListenerInternal(executor, /* filter= */null, listener);
844     }
845 
846     /**
847      * Adds a listener for {@link UserLifecycleEvent user lifecycle events} with a filter that can
848      * specify a specific event type or a user id.
849      *
850      * @throws IllegalStateException if the listener was already added.
851      *
852      * @hide
853      */
854     @SystemApi
855     @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener)856     public void addListener(@NonNull @CallbackExecutor Executor executor,
857             @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener) {
858         Objects.requireNonNull(filter, "filter cannot be null");
859 
860         addListenerInternal(executor, filter, listener);
861     }
862 
addListenerInternal(@allbackExecutor Executor executor, @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener)863     private void addListenerInternal(@CallbackExecutor Executor executor,
864             @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener) {
865         Objects.requireNonNull(executor, "executor cannot be null");
866         Objects.requireNonNull(listener, "listener cannot be null");
867 
868         int uid = myUid();
869         String packageName = getContext().getPackageName();
870         if (DBG) {
871             Slog.d(TAG, "addListener(): uid=" + uid + ", pkg=" + packageName
872                     + ", listener=" + listener + ", filter= " + filter);
873         }
874         synchronized (mLock) {
875             Preconditions.checkState(mListeners == null || !mListeners.containsKey(listener),
876                     "already called for this listener");
877             if (mReceiver == null) {
878                 mReceiver = new LifecycleResultReceiver();
879                 if (DBG) {
880                     Slog.d(TAG, "Setting lifecycle receiver with filter " + filter
881                             + " for uid " + uid + " and package " + packageName);
882                 }
883             } else {
884                 if (DBG) {
885                     Slog.d(TAG, "Already set receiver for uid " + uid + " and package "
886                             + packageName + " adding new filter " + filter);
887                 }
888             }
889             try {
890                 boolean hasFilter = filter != null;
891                 EventLogHelper.writeCarUserManagerAddListener(uid, packageName, hasFilter);
892                 mService.setLifecycleListenerForApp(packageName, filter, mReceiver);
893             } catch (RemoteException e) {
894                 handleRemoteExceptionFromCarService(e);
895             }
896 
897             if (mListeners == null) {
898                 mListeners = new ArrayMap<>(1); // Most likely app will have just one listener
899             } else if (DBG) {
900                 Slog.d(TAG, "addListener(" + getLambdaName(listener) + "): context " + getContext()
901                         + " already has " + mListeners.size() + " listeners: "
902                         + mListeners.keySet().stream()
903                                 .map((l) -> getLambdaName(l))
904                                 .collect(Collectors.toList()), new Exception("caller's stack"));
905             }
906             if (DBG) Slog.d(TAG, "Adding listener: " + listener + " with filter " + filter);
907             mListeners.put(listener, Pair.create(filter, executor));
908         }
909     }
910 
911     /**
912      * Removes a listener for {@link UserLifecycleEvent user lifecycle events}.
913      *
914      * @throws IllegalStateException if the listener was not added beforehand.
915      *
916      * @hide
917      */
918     @SystemApi
919     @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
removeListener(@onNull UserLifecycleListener listener)920     public void removeListener(@NonNull UserLifecycleListener listener) {
921         Objects.requireNonNull(listener, "listener cannot be null");
922 
923         int uid = myUid();
924         String packageName = getContext().getPackageName();
925         if (DBG) {
926             Slog.d(TAG, "removeListener(): uid=" + uid + ", pkg=" + packageName
927                     + ", listener=" + listener);
928         }
929         synchronized (mLock) {
930             Preconditions.checkState(mListeners != null && mListeners.containsKey(listener),
931                     "not called for this listener yet");
932             mListeners.remove(listener);
933 
934             // Note that there can be some rare corner cases that a listener is removed but its
935             // corresponding filter remains in the service side. This may cause slight inefficiency
936             // due to unnecessary receiver calls. It will still be functionally correct, because the
937             // removed listener will no longer be invoked.
938             if (!mListeners.isEmpty()) {
939                 if (DBG) Slog.d(TAG, "removeListeners(): still " + mListeners.size() + " left");
940                 return;
941             }
942             mListeners = null;
943 
944             if (mReceiver == null) {
945                 Slog.wtf(TAG, "removeListener(): receiver already null");
946                 return;
947             }
948 
949             EventLogHelper.writeCarUserManagerRemoveListener(uid, packageName);
950             if (DBG) {
951                 Slog.d(TAG, "Removing lifecycle receiver for uid=" + uid + " and package "
952                         + packageName);
953             }
954             try {
955                 mService.resetLifecycleListenerForApp(mReceiver);
956                 mReceiver = null;
957             } catch (RemoteException e) {
958                 handleRemoteExceptionFromCarService(e);
959             }
960         }
961     }
962 
963     /**
964      * Check if user hal supports user association.
965      *
966      * @hide
967      */
isUserHalUserAssociationSupported()968     public boolean isUserHalUserAssociationSupported() {
969         try {
970             return mService.isUserHalUserAssociationSupported();
971         } catch (RemoteException | RuntimeException e) {
972             return handleExceptionFromCarService(e, false);
973         }
974     }
975 
976     /**
977      * Gets the user authentication types associated with this manager's user.
978      *
979      * @hide
980      */
981     @NonNull
982     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
983             android.Manifest.permission.CREATE_USERS})
getUserIdentificationAssociation( @serIdentificationAssociationType int... types)984     public UserIdentificationAssociationResponse getUserIdentificationAssociation(
985             @UserIdentificationAssociationType int... types) {
986         Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
987         EventLogHelper.writeCarUserManagerGetUserAuthReq(convertToObjectArray(types));
988         try {
989             UserIdentificationAssociationResponse response =
990                     mService.getUserIdentificationAssociation(types);
991             if (response != null) {
992                 int[] values = response.getValues();
993                 EventLogHelper.writeCarUserManagerGetUserAuthResp(convertToObjectArray(values));
994             }
995             return response;
996         } catch (SecurityException e) {
997             throw e;
998         } catch (RemoteException | RuntimeException e) {
999             return handleExceptionFromCarService(e,
1000                     UserIdentificationAssociationResponse.forFailure(e.getMessage()));
1001         }
1002     }
1003 
1004     @Nullable
convertToObjectArray(int[] input)1005     private Object[] convertToObjectArray(int[] input) {
1006         if (input == null) return null;
1007         Object[] output = new Object[input.length];
1008         for (int i = 0; i < input.length; i++) {
1009             output[i] = input[i];
1010         }
1011         return output;
1012     }
1013 
1014     /**
1015      * Sets the user authentication types associated with this manager's user.
1016      *
1017      * @hide
1018      */
1019     @NonNull
1020     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
1021             android.Manifest.permission.CREATE_USERS})
setUserIdentificationAssociation( @serIdentificationAssociationType int[] types, @UserIdentificationAssociationSetValue int[] values)1022     public AsyncFuture<UserIdentificationAssociationResponse> setUserIdentificationAssociation(
1023             @UserIdentificationAssociationType int[] types,
1024             @UserIdentificationAssociationSetValue int[] values) {
1025         Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1026         Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1027         if (types.length != values.length) {
1028             throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1029                     + Arrays.toString(values) + ") should have the same length");
1030         }
1031         // TODO(b/153900032): move this logic to a common helper
1032         Object[] loggedValues = new Integer[types.length * 2];
1033         for (int i = 0; i < types.length; i++) {
1034             loggedValues[i * 2] = types[i];
1035             loggedValues[i * 2 + 1 ] = values[i];
1036         }
1037         EventLogHelper.writeCarUserManagerSetUserAuthReq(loggedValues);
1038 
1039         try {
1040             AndroidFuture<UserIdentificationAssociationResponse> future =
1041                     new AndroidFuture<UserIdentificationAssociationResponse>() {
1042                 @Override
1043                 protected void onCompleted(UserIdentificationAssociationResponse result,
1044                         Throwable err) {
1045                     if (result != null) {
1046                         int[] rawValues = result.getValues();
1047                         // TODO(b/153900032): move this logic to a common helper
1048                         if (rawValues != null) {
1049                             Object[] loggedValues = new Object[rawValues.length];
1050                             for (int i = 0; i < rawValues.length; i++) {
1051                                 loggedValues[i] = rawValues[i];
1052                             }
1053                             EventLogHelper.writeCarUserManagerSetUserAuthResp(loggedValues);
1054                         }
1055                     } else {
1056                         Slog.w(TAG, "setUserIdentificationAssociation(" + Arrays.toString(types)
1057                                 + ", " + Arrays.toString(values) + ") failed: " + err);
1058                     }
1059                     super.onCompleted(result, err);
1060                 };
1061             };
1062             mService.setUserIdentificationAssociation(HAL_TIMEOUT_MS, types, values, future);
1063             return new AndroidAsyncFuture<>(future);
1064         } catch (SecurityException e) {
1065             throw e;
1066         } catch (RemoteException | RuntimeException e) {
1067             AndroidFuture<UserIdentificationAssociationResponse> future = new AndroidFuture<>();
1068             future.complete(UserIdentificationAssociationResponse.forFailure());
1069             return handleExceptionFromCarService(e, new AndroidAsyncFuture<>(future));
1070         }
1071     }
1072 
1073     /**
1074      * Sets a callback to be notified before user switch. It should only be used by Car System UI.
1075      *
1076      * @hide
1077      * @deprecated use {@link #setUserSwitchUiCallback(Executor, UserHandleSwitchUiCallback)}
1078      * instead.
1079      */
1080     @Deprecated
1081     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
setUserSwitchUiCallback(@onNull UserSwitchUiCallback callback)1082     public void setUserSwitchUiCallback(@NonNull UserSwitchUiCallback callback) {
1083         Preconditions.checkArgument(callback != null, "Null callback");
1084         UserHandleSwitchUiCallback userHandleSwitchUiCallback = (userHandle) -> {
1085             callback.showUserSwitchDialog(userHandle.getIdentifier());
1086         };
1087         setUserSwitchUiCallback(Runnable::run, userHandleSwitchUiCallback);
1088     }
1089 
1090     /**
1091      * Sets a callback to be notified before user switch.
1092      *
1093      * <p> It should only be used by Car System UI. Setting this callback will notify the Car
1094      * System UI to show the user switching dialog.
1095      *
1096      * @hide
1097      */
1098     @SystemApi
1099     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
setUserSwitchUiCallback(@onNull @allbackExecutor Executor executor, @NonNull UserHandleSwitchUiCallback callback)1100     public void setUserSwitchUiCallback(@NonNull @CallbackExecutor Executor executor,
1101             @NonNull UserHandleSwitchUiCallback callback) {
1102         Preconditions.checkArgument(callback != null, "Null callback");
1103         UserSwitchUiCallbackReceiver userSwitchUiCallbackReceiver =
1104                 new UserSwitchUiCallbackReceiver(callback);
1105         try {
1106             mService.setUserSwitchUiCallback(userSwitchUiCallbackReceiver);
1107         } catch (RemoteException e) {
1108             handleRemoteExceptionFromCarService(e);
1109         }
1110     }
1111 
1112     // TODO(b/154958003): use mReceiver instead as now there are two binder objects
1113     /**
1114      * {@code ICarResultReceiver} used to receive user switch UI Callback.
1115      */
1116     private final class UserSwitchUiCallbackReceiver extends ICarResultReceiver.Stub {
1117 
1118         private final UserHandleSwitchUiCallback mUserHandleSwitchUiCallback;
1119 
UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback)1120         UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback) {
1121             mUserHandleSwitchUiCallback = callback;
1122         }
1123 
1124         @Override
send(int userId, Bundle unused)1125         public void send(int userId, Bundle unused) throws RemoteException {
1126             mUserHandleSwitchUiCallback.onUserSwitchStart(UserHandle.of(userId));
1127         }
1128     }
1129 
1130     /**
1131      * {@code ICarResultReceiver} used to receive lifecycle events and dispatch to the proper
1132      * listener.
1133      */
1134     private class LifecycleResultReceiver extends ICarResultReceiver.Stub {
1135         @Override
send(int resultCode, Bundle resultData)1136         public void send(int resultCode, Bundle resultData) {
1137             if (resultData == null) {
1138                 Slog.w(TAG, "Received result (" + resultCode + ") without data");
1139                 return;
1140             }
1141             int from = resultData.getInt(BUNDLE_PARAM_PREVIOUS_USER_ID,
1142                     UserManagerHelper.USER_NULL);
1143             int to = resultCode;
1144             int eventType = resultData.getInt(BUNDLE_PARAM_ACTION);
1145             UserLifecycleEvent event = new UserLifecycleEvent(eventType, from, to);
1146             ArrayMap<UserLifecycleListener, Pair<UserLifecycleEventFilter, Executor>> listeners;
1147             synchronized (mLock) {
1148                 if (mListeners == null) {
1149                     Slog.w(TAG, "No listeners for event " + event);
1150                     return;
1151                 }
1152                 listeners = new ArrayMap<>(mListeners);
1153             }
1154             int size = listeners.size();
1155             EventLogHelper.writeCarUserManagerNotifyLifecycleListener(size, eventType, from, to);
1156             for (int i = 0; i < size; i++) {
1157                 UserLifecycleListener listener = listeners.keyAt(i);
1158                 UserLifecycleEventFilter filter = listeners.valueAt(i).first;
1159                 if (filter != null && !filter.apply(event)) {
1160                     if (DBG) {
1161                         Slog.d(TAG, "Listener " + getLambdaName(listener)
1162                                 + " is skipped for the event " + event + " due to the filter "
1163                                 + filter);
1164                     }
1165                     continue;
1166                 }
1167                 Executor executor = listeners.valueAt(i).second;
1168                 if (DBG) {
1169                     Slog.d(TAG, "Calling " + getLambdaName(listener) + " for event " + event);
1170                 }
1171                 executor.execute(() -> listener.onEvent(event));
1172             }
1173             mNumberReceivedEvents++;
1174             if (VERBOSE) {
1175                 if (mEvents == null) {
1176                     mEvents = new ArrayList<>();
1177                 }
1178                 mEvents.add(event);
1179             }
1180         }
1181     }
1182 
1183     /** @hide */
1184     @Override
onCarDisconnected()1185     public void onCarDisconnected() {
1186         // nothing to do
1187     }
1188 
1189     private final class Dumper implements Dumpable {
1190         @Override
dump(PrintWriter pw, String[] args)1191         public void dump(PrintWriter pw, String[] args) {
1192             String prefix = "  ";
1193 
1194             pw.printf("DBG=%b, VERBOSE=%b\n", DBG, VERBOSE);
1195             int listenersSize = 0;
1196             synchronized (mLock) {
1197                 pw.printf("mReceiver: %s\n", mReceiver);
1198                 if (mListeners == null) {
1199                     pw.println("no listeners");
1200                 } else {
1201                     listenersSize = mListeners.size();
1202                     pw.printf("%d listeners\n", listenersSize);
1203                 }
1204                 if (DBG) {
1205                     for (int i = 0; i < listenersSize; i++) {
1206                         pw.printf("%s%d: %s\n", prefix, i + 1, mListeners.keyAt(i));
1207                     }
1208                 }
1209             }
1210             pw.printf("mNumberReceivedEvents: %d\n", mNumberReceivedEvents);
1211             if (VERBOSE && mEvents != null) {
1212                 for (int i = 0; i < mEvents.size(); i++) {
1213                     pw.printf("%s%d: %s\n", prefix, i + 1, mEvents.get(i));
1214                 }
1215             }
1216         }
1217 
1218         @Override
getDumpableName()1219         public String getDumpableName() {
1220             return CarUserManager.class.getSimpleName();
1221         }
1222     }
1223 
1224     /**
1225      * @hide
1226      */
1227     @SystemApi
1228     @NonNull
lifecycleEventTypeToString(@serLifecycleEventType int type)1229     public static String lifecycleEventTypeToString(@UserLifecycleEventType int type) {
1230         switch (type) {
1231             case USER_LIFECYCLE_EVENT_TYPE_STARTING:
1232                 return "STARTING";
1233             case USER_LIFECYCLE_EVENT_TYPE_SWITCHING:
1234                 return "SWITCHING";
1235             case USER_LIFECYCLE_EVENT_TYPE_UNLOCKING:
1236                 return "UNLOCKING";
1237             case USER_LIFECYCLE_EVENT_TYPE_UNLOCKED:
1238                 return "UNLOCKED";
1239             case USER_LIFECYCLE_EVENT_TYPE_STOPPING:
1240                 return "STOPPING";
1241             case USER_LIFECYCLE_EVENT_TYPE_STOPPED:
1242                 return "STOPPED";
1243             case USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED:
1244                 return "POST_UNLOCKED";
1245             case USER_LIFECYCLE_EVENT_TYPE_CREATED:
1246                 return "CREATED";
1247             case USER_LIFECYCLE_EVENT_TYPE_REMOVED:
1248                 return "REMOVED";
1249             case USER_LIFECYCLE_EVENT_TYPE_VISIBLE:
1250                 return "VISIBLE";
1251             case USER_LIFECYCLE_EVENT_TYPE_INVISIBLE:
1252                 return "INVISIBLE";
1253             default:
1254                 return "UNKNOWN-" + type;
1255         }
1256     }
1257 
1258     /**
1259      * Checks if the given {@code userId} represents a valid user.
1260      *
1261      * <p>A "valid" user:
1262      *
1263      * <ul>
1264      *   <li>Must exist in the device.
1265      *   <li>Is not in the process of being deleted.
1266      *   <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use
1267      *   {@link UserManager#isHeadlessSystemUserMode() headless system user mode}.
1268      * </ul>
1269      *
1270      * @hide
1271      * @deprecated use {@link #isValidUser(UserHandle)} instead.
1272      */
1273     @Deprecated
1274     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
1275             android.Manifest.permission.CREATE_USERS})
isValidUser(@serIdInt int userId)1276     public boolean isValidUser(@UserIdInt int userId) {
1277         return isValidUser(UserHandle.of(userId));
1278     }
1279 
1280     /**
1281      * Checks if the given {@code userHandle} represents a valid user.
1282      *
1283      * <p>A "valid" user:
1284      *
1285      * <ul>
1286      *   <li>Must exist in the device.
1287      *   <li>Is not in the process of being deleted.
1288      *   <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use
1289      *   {@link UserManager#isHeadlessSystemUserMode() headless system user mode}.
1290      * </ul>
1291      *
1292      */
1293     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
1294             android.Manifest.permission.CREATE_USERS})
1295     @SuppressWarnings("UserHandle")
isValidUser(@onNull UserHandle userHandle)1296     public boolean isValidUser(@NonNull UserHandle userHandle) {
1297         List<UserHandle> allUsers = mUserManager.getUserHandles(/* excludeDying=*/ true);
1298         for (int i = 0; i < allUsers.size(); i++) {
1299             UserHandle user = allUsers.get(i);
1300             if (user.equals(userHandle) && (!userHandle.equals(UserHandle.SYSTEM)
1301                     || !mIsHeadlessSystemUserMode)) {
1302                 return true;
1303             }
1304         }
1305         return false;
1306     }
1307 
1308     /**
1309      * Defines a lifecycle event for an Android user.
1310      *
1311      * @hide
1312      */
1313     @SystemApi
1314     public static final class UserLifecycleEvent {
1315         private final @UserLifecycleEventType int mEventType;
1316         private final @UserIdInt int mUserId;
1317         private final @UserIdInt int mPreviousUserId;
1318 
1319         /** @hide */
UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int from, @UserIdInt int to)1320         public UserLifecycleEvent(@UserLifecycleEventType int eventType,
1321                 @UserIdInt int from, @UserIdInt int to) {
1322             mEventType = eventType;
1323             mPreviousUserId = from;
1324             mUserId = to;
1325         }
1326 
1327         /** @hide */
UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int to)1328         public UserLifecycleEvent(@UserLifecycleEventType int eventType, @UserIdInt int to) {
1329             this(eventType, UserManagerHelper.USER_NULL, to);
1330         }
1331 
1332         /**
1333          * Gets the event type.
1334          *
1335          * @return either {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STARTING},
1336          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING},
1337          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKING},
1338          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKED},
1339          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPING} or
1340          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPED} for all apps;
1341          * for apps {@link CarPackageManager#getTargetCarVersion() targeting car version}
1342          * {@link CarVersion.VERSION_CODES#TIRAMISU_1} or higher, it could be new types
1343          * added on later releases, such as
1344          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_CREATED},
1345          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_REMOVED} and possibly others.
1346          *
1347          */
1348         @UserLifecycleEventType
getEventType()1349         public int getEventType() {
1350             return mEventType;
1351         }
1352 
1353         /**
1354          * Gets the id of the user whose event is being reported.
1355          *
1356          * @hide
1357          */
1358         @UserIdInt
getUserId()1359         public int getUserId() {
1360             return mUserId;
1361         }
1362 
1363         /**
1364          * Gets the handle of the user whose event is being reported.
1365          */
1366         @NonNull
getUserHandle()1367         public UserHandle getUserHandle() {
1368             return UserHandle.of(mUserId);
1369         }
1370 
1371         /**
1372          * Gets the id of the user being switched from.
1373          *
1374          * <p>This method returns {@link UserHandle#USER_NULL} for all event types but
1375          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}.
1376          *
1377          * @hide
1378          */
1379         @UserIdInt
getPreviousUserId()1380         public int getPreviousUserId() {
1381             return mPreviousUserId;
1382         }
1383 
1384         /**
1385          * Gets the handle of the user being switched from.
1386          *
1387          * <p>This method returns {@code null} for all event types but
1388          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}.
1389          */
1390         @Nullable
getPreviousUserHandle()1391         public UserHandle getPreviousUserHandle() {
1392             return mPreviousUserId == UserManagerHelper.USER_NULL ? null
1393                     : UserHandle.of(mPreviousUserId);
1394         }
1395 
1396         @Override
toString()1397         public String toString() {
1398             StringBuilder builder = new StringBuilder("Event[type=")
1399                     .append(lifecycleEventTypeToString(mEventType));
1400             if (mPreviousUserId != UserManagerHelper.USER_NULL) {
1401                 builder
1402                     .append(",from=").append(mPreviousUserId)
1403                     .append(",to=").append(mUserId);
1404             } else {
1405                 builder.append(",user=").append(mUserId);
1406             }
1407 
1408             return builder.append(']').toString();
1409         }
1410 
1411         @Override
equals(@ullable Object o)1412         public boolean equals(@Nullable Object o) {
1413             if (this == o) return true;
1414             if (o == null || getClass() != o.getClass()) return false;
1415 
1416             UserLifecycleEvent that = (UserLifecycleEvent) o;
1417             return mEventType == that.mEventType && mUserId == that.mUserId
1418                     && mPreviousUserId == that.mPreviousUserId;
1419         }
1420 
1421         @Override
hashCode()1422         public int hashCode() {
1423             int hash = 23;
1424             hash = 17 * hash + mEventType;
1425             hash = 17 * hash + mUserId;
1426             hash = 17 * hash + mPreviousUserId;
1427 
1428             return hash;
1429         }
1430     }
1431 
1432     /**
1433      * Listener for Android User lifecycle events.
1434      *
1435      * <p>Must be registered using {@link CarUserManager#addListener(UserLifecycleListener)} and
1436      * unregistered through {@link CarUserManager#removeListener(UserLifecycleListener)}.
1437      *
1438      * @hide
1439      */
1440     @SystemApi
1441     public interface UserLifecycleListener {
1442 
1443         /**
1444          * Called to notify the given {@code event}.
1445          */
onEvent(@onNull UserLifecycleEvent event)1446         void onEvent(@NonNull UserLifecycleEvent event);
1447     }
1448 
1449     /**
1450      * Callback for notifying user switch before switch started.
1451      *
1452      * <p> It should only be used by Car System UI. The purpose of this callback is to notify the
1453      * Car System UI to display the user switch UI.
1454      *
1455      * @hide
1456      * @deprecated use {@link #UserHandleSwitchUiCallback} instead.
1457      */
1458     @Deprecated
1459     public interface UserSwitchUiCallback {
1460 
1461         /**
1462          * Called to notify that user switch dialog should be shown now.
1463          */
showUserSwitchDialog(@serIdInt int userId)1464         void showUserSwitchDialog(@UserIdInt int userId);
1465     }
1466 
1467     /**
1468      * Callback for notifying user switch before switch started.
1469      *
1470      * @hide
1471      */
1472     @SystemApi
1473     public interface UserHandleSwitchUiCallback {
1474 
1475         /**
1476          * Called before the user switch starts.
1477          *
1478          * <p> This is typically used to show the user dialog.
1479          */
1480         @SuppressWarnings("UserHandleName")
onUserSwitchStart(@onNull UserHandle userHandle)1481         void onUserSwitchStart(@NonNull UserHandle userHandle);
1482     }
1483 }
1484