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             System.out.println("manager test API replied");
726         } catch (SecurityException e) {
727             throw e;
728         } catch (RemoteException | RuntimeException e) {
729             callback.onResult(
730                     new UserCreationResult(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE));
731             handleExceptionFromCarService(e, null);
732         }
733     }
734 
735     /**
736      * Updates pre-created users.
737      *
738      * @deprecated Pre-created users are no longer supported.
739      *             This method is no-op and will be removed soon.
740      *
741      * @hide
742      */
743     @Deprecated
744     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
745             android.Manifest.permission.CREATE_USERS})
updatePreCreatedUsers()746     public void updatePreCreatedUsers() {
747         Slog.w(TAG, "updatePreCreatedUsers(): This method should not be called."
748                 + " Pre-created users are no longer supported.");
749     }
750 
751 
752     /**
753      * Removes the given user.
754      *
755      * @param userRemovalRequest contains user to be removed.
756      * @param executor to execute the callback.
757      * @param callback called with the {code UserRemovalResult}
758      *
759      * @hide
760      */
761     @SystemApi
762     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
763             android.Manifest.permission.CREATE_USERS})
removeUser(@onNull UserRemovalRequest userRemovalRequest, @NonNull @CallbackExecutor Executor executor, @NonNull ResultCallback<UserRemovalResult> callback)764     public void removeUser(@NonNull UserRemovalRequest userRemovalRequest,
765             @NonNull @CallbackExecutor Executor executor,
766             @NonNull ResultCallback<UserRemovalResult> callback) {
767         int uid = myUid();
768         EventLogHelper.writeCarUserManagerRemoveUserReq(uid,
769                 userRemovalRequest.getUserHandle().getIdentifier());
770         try {
771             ResultCallbackImpl<UserRemovalResult> resultCallbackImpl = new ResultCallbackImpl<>(
772                     executor, callback) {
773                 @Override
774                 protected void onCompleted(UserRemovalResult result) {
775                     EventLogHelper.writeCarUserManagerRemoveUserResp(uid,
776                             result != null ? result.getStatus()
777                                     : UserRemovalResult.STATUS_ANDROID_FAILURE);
778                     super.onCompleted(result);
779                 }
780             };
781             mService.removeUser(userRemovalRequest.getUserHandle().getIdentifier(),
782                     resultCallbackImpl);
783         } catch (SecurityException e) {
784             Slog.e(TAG, "CarUserManager removeUser", e);
785             throw e;
786         } catch (RemoteException | RuntimeException e) {
787             UserRemovalResult result = handleExceptionFromCarService(e,
788                     new UserRemovalResult(UserRemovalResult.STATUS_ANDROID_FAILURE));
789             callback.onResult(result);
790         }
791     }
792 
793     /**
794      * Removes the given user.
795      *
796      * @param userId identification of the user to be removed.
797      *
798      * @return whether the user was successfully removed.
799      *
800      * @hide
801      *
802      * @deprecated use {@link #removeUser(UserRemovalRequest, Executor, ResultCallback)} instead.
803      * It will be marked removed in {@code V} and hard removed in {@code X}.
804      */
805     @Deprecated
806     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
807             android.Manifest.permission.CREATE_USERS})
808     @NonNull
removeUser(@serIdInt int userId)809     public UserRemovalResult removeUser(@UserIdInt int userId) {
810         UserRemovalRequest userRemovalRequest = new UserRemovalRequest.Builder(
811                 UserHandle.of(userId)).build();
812         SyncResultCallback<UserRemovalResult> userRemovalResultCallback =
813                 new SyncResultCallback<>();
814 
815         removeUser(userRemovalRequest, Runnable::run, userRemovalResultCallback);
816 
817         UserRemovalResult userRemovalResult = new UserRemovalResult(
818                 UserRemovalResult.STATUS_ANDROID_FAILURE);
819 
820         try {
821             userRemovalResult = userRemovalResultCallback.get(USER_CALL_TIMEOUT_MS,
822                     TimeUnit.MILLISECONDS);
823         } catch (TimeoutException e) {
824             Slog.e(TAG, "CarUserManager removeUser(" + userId + "): ", e);
825         } catch (InterruptedException e) {
826             Thread.currentThread().interrupt();
827             Slog.e(TAG, "CarUserManager removeUser(" + userId + "): ", e);
828         }
829 
830         return userRemovalResult;
831     }
832 
833     /**
834      * Adds a listener for {@link UserLifecycleEvent user lifecycle events}.
835      *
836      * @throws IllegalStateException if the listener was already added.
837      *
838      * @hide
839      */
840     @SystemApi
841     @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleListener listener)842     public void addListener(@NonNull @CallbackExecutor Executor executor,
843             @NonNull UserLifecycleListener listener) {
844         addListenerInternal(executor, /* filter= */null, listener);
845     }
846 
847     /**
848      * Adds a listener for {@link UserLifecycleEvent user lifecycle events} with a filter that can
849      * specify a specific event type or a user id.
850      *
851      * @throws IllegalStateException if the listener was already added.
852      *
853      * @hide
854      */
855     @SystemApi
856     @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
addListener(@onNull @allbackExecutor Executor executor, @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener)857     public void addListener(@NonNull @CallbackExecutor Executor executor,
858             @NonNull UserLifecycleEventFilter filter, @NonNull UserLifecycleListener listener) {
859         Objects.requireNonNull(filter, "filter cannot be null");
860 
861         addListenerInternal(executor, filter, listener);
862     }
863 
addListenerInternal(@allbackExecutor Executor executor, @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener)864     private void addListenerInternal(@CallbackExecutor Executor executor,
865             @Nullable UserLifecycleEventFilter filter, UserLifecycleListener listener) {
866         Objects.requireNonNull(executor, "executor cannot be null");
867         Objects.requireNonNull(listener, "listener cannot be null");
868 
869         int uid = myUid();
870         String packageName = getContext().getPackageName();
871         if (DBG) {
872             Slog.d(TAG, "addListener(): uid=" + uid + ", pkg=" + packageName
873                     + ", listener=" + listener + ", filter= " + filter);
874         }
875         synchronized (mLock) {
876             Preconditions.checkState(mListeners == null || !mListeners.containsKey(listener),
877                     "already called for this listener");
878             if (mReceiver == null) {
879                 mReceiver = new LifecycleResultReceiver();
880                 if (DBG) {
881                     Slog.d(TAG, "Setting lifecycle receiver with filter " + filter
882                             + " for uid " + uid + " and package " + packageName);
883                 }
884             } else {
885                 if (DBG) {
886                     Slog.d(TAG, "Already set receiver for uid " + uid + " and package "
887                             + packageName + " adding new filter " + filter);
888                 }
889             }
890             try {
891                 boolean hasFilter = filter != null;
892                 EventLogHelper.writeCarUserManagerAddListener(uid, packageName, hasFilter);
893                 mService.setLifecycleListenerForApp(packageName, filter, mReceiver);
894             } catch (RemoteException e) {
895                 handleRemoteExceptionFromCarService(e);
896             }
897 
898             if (mListeners == null) {
899                 mListeners = new ArrayMap<>(1); // Most likely app will have just one listener
900             } else if (DBG) {
901                 Slog.d(TAG, "addListener(" + getLambdaName(listener) + "): context " + getContext()
902                         + " already has " + mListeners.size() + " listeners: "
903                         + mListeners.keySet().stream()
904                                 .map((l) -> getLambdaName(l))
905                                 .collect(Collectors.toList()), new Exception("caller's stack"));
906             }
907             if (DBG) Slog.d(TAG, "Adding listener: " + listener + " with filter " + filter);
908             mListeners.put(listener, Pair.create(filter, executor));
909         }
910     }
911 
912     /**
913      * Removes a listener for {@link UserLifecycleEvent user lifecycle events}.
914      *
915      * @throws IllegalStateException if the listener was not added beforehand.
916      *
917      * @hide
918      */
919     @SystemApi
920     @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
removeListener(@onNull UserLifecycleListener listener)921     public void removeListener(@NonNull UserLifecycleListener listener) {
922         Objects.requireNonNull(listener, "listener cannot be null");
923 
924         int uid = myUid();
925         String packageName = getContext().getPackageName();
926         if (DBG) {
927             Slog.d(TAG, "removeListener(): uid=" + uid + ", pkg=" + packageName
928                     + ", listener=" + listener);
929         }
930         synchronized (mLock) {
931             Preconditions.checkState(mListeners != null && mListeners.containsKey(listener),
932                     "not called for this listener yet");
933             mListeners.remove(listener);
934 
935             // Note that there can be some rare corner cases that a listener is removed but its
936             // corresponding filter remains in the service side. This may cause slight inefficiency
937             // due to unnecessary receiver calls. It will still be functionally correct, because the
938             // removed listener will no longer be invoked.
939             if (!mListeners.isEmpty()) {
940                 if (DBG) Slog.d(TAG, "removeListeners(): still " + mListeners.size() + " left");
941                 return;
942             }
943             mListeners = null;
944 
945             if (mReceiver == null) {
946                 Slog.wtf(TAG, "removeListener(): receiver already null");
947                 return;
948             }
949 
950             EventLogHelper.writeCarUserManagerRemoveListener(uid, packageName);
951             if (DBG) {
952                 Slog.d(TAG, "Removing lifecycle receiver for uid=" + uid + " and package "
953                         + packageName);
954             }
955             try {
956                 mService.resetLifecycleListenerForApp(mReceiver);
957                 mReceiver = null;
958             } catch (RemoteException e) {
959                 handleRemoteExceptionFromCarService(e);
960             }
961         }
962     }
963 
964     /**
965      * Check if user hal supports user association.
966      *
967      * @hide
968      */
isUserHalUserAssociationSupported()969     public boolean isUserHalUserAssociationSupported() {
970         try {
971             return mService.isUserHalUserAssociationSupported();
972         } catch (RemoteException | RuntimeException e) {
973             return handleExceptionFromCarService(e, false);
974         }
975     }
976 
977     /**
978      * Gets the user authentication types associated with this manager's user.
979      *
980      * @hide
981      */
982     @NonNull
983     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
984             android.Manifest.permission.CREATE_USERS})
getUserIdentificationAssociation( @serIdentificationAssociationType int... types)985     public UserIdentificationAssociationResponse getUserIdentificationAssociation(
986             @UserIdentificationAssociationType int... types) {
987         Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
988         EventLogHelper.writeCarUserManagerGetUserAuthReq(convertToObjectArray(types));
989         try {
990             UserIdentificationAssociationResponse response =
991                     mService.getUserIdentificationAssociation(types);
992             if (response != null) {
993                 int[] values = response.getValues();
994                 EventLogHelper.writeCarUserManagerGetUserAuthResp(convertToObjectArray(values));
995             }
996             return response;
997         } catch (SecurityException e) {
998             throw e;
999         } catch (RemoteException | RuntimeException e) {
1000             return handleExceptionFromCarService(e,
1001                     UserIdentificationAssociationResponse.forFailure(e.getMessage()));
1002         }
1003     }
1004 
1005     @Nullable
convertToObjectArray(int[] input)1006     private Object[] convertToObjectArray(int[] input) {
1007         if (input == null) return null;
1008         Object[] output = new Object[input.length];
1009         for (int i = 0; i < input.length; i++) {
1010             output[i] = input[i];
1011         }
1012         return output;
1013     }
1014 
1015     /**
1016      * Sets the user authentication types associated with this manager's user.
1017      *
1018      * @hide
1019      */
1020     @NonNull
1021     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
1022             android.Manifest.permission.CREATE_USERS})
setUserIdentificationAssociation( @serIdentificationAssociationType int[] types, @UserIdentificationAssociationSetValue int[] values)1023     public AsyncFuture<UserIdentificationAssociationResponse> setUserIdentificationAssociation(
1024             @UserIdentificationAssociationType int[] types,
1025             @UserIdentificationAssociationSetValue int[] values) {
1026         Preconditions.checkArgument(!ArrayUtils.isEmpty(types), "must have at least one type");
1027         Preconditions.checkArgument(!ArrayUtils.isEmpty(values), "must have at least one value");
1028         if (types.length != values.length) {
1029             throw new IllegalArgumentException("types (" + Arrays.toString(types) + ") and values ("
1030                     + Arrays.toString(values) + ") should have the same length");
1031         }
1032         // TODO(b/153900032): move this logic to a common helper
1033         Object[] loggedValues = new Integer[types.length * 2];
1034         for (int i = 0; i < types.length; i++) {
1035             loggedValues[i * 2] = types[i];
1036             loggedValues[i * 2 + 1 ] = values[i];
1037         }
1038         EventLogHelper.writeCarUserManagerSetUserAuthReq(loggedValues);
1039 
1040         try {
1041             AndroidFuture<UserIdentificationAssociationResponse> future =
1042                     new AndroidFuture<UserIdentificationAssociationResponse>() {
1043                 @Override
1044                 protected void onCompleted(UserIdentificationAssociationResponse result,
1045                         Throwable err) {
1046                     if (result != null) {
1047                         int[] rawValues = result.getValues();
1048                         // TODO(b/153900032): move this logic to a common helper
1049                         if (rawValues != null) {
1050                             Object[] loggedValues = new Object[rawValues.length];
1051                             for (int i = 0; i < rawValues.length; i++) {
1052                                 loggedValues[i] = rawValues[i];
1053                             }
1054                             EventLogHelper.writeCarUserManagerSetUserAuthResp(loggedValues);
1055                         }
1056                     } else {
1057                         Slog.w(TAG, "setUserIdentificationAssociation(" + Arrays.toString(types)
1058                                 + ", " + Arrays.toString(values) + ") failed: " + err);
1059                     }
1060                     super.onCompleted(result, err);
1061                 };
1062             };
1063             mService.setUserIdentificationAssociation(HAL_TIMEOUT_MS, types, values, future);
1064             return new AndroidAsyncFuture<>(future);
1065         } catch (SecurityException e) {
1066             throw e;
1067         } catch (RemoteException | RuntimeException e) {
1068             AndroidFuture<UserIdentificationAssociationResponse> future = new AndroidFuture<>();
1069             future.complete(UserIdentificationAssociationResponse.forFailure());
1070             return handleExceptionFromCarService(e, new AndroidAsyncFuture<>(future));
1071         }
1072     }
1073 
1074     /**
1075      * Sets a callback to be notified before user switch. It should only be used by Car System UI.
1076      *
1077      * @hide
1078      * @deprecated use {@link #setUserSwitchUiCallback(Executor, UserHandleSwitchUiCallback)}
1079      * instead.
1080      */
1081     @Deprecated
1082     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
setUserSwitchUiCallback(@onNull UserSwitchUiCallback callback)1083     public void setUserSwitchUiCallback(@NonNull UserSwitchUiCallback callback) {
1084         Preconditions.checkArgument(callback != null, "Null callback");
1085         UserHandleSwitchUiCallback userHandleSwitchUiCallback = (userHandle) -> {
1086             callback.showUserSwitchDialog(userHandle.getIdentifier());
1087         };
1088         setUserSwitchUiCallback(Runnable::run, userHandleSwitchUiCallback);
1089     }
1090 
1091     /**
1092      * Sets a callback to be notified before user switch.
1093      *
1094      * <p> It should only be used by Car System UI. Setting this callback will notify the Car
1095      * System UI to show the user switching dialog.
1096      *
1097      * @hide
1098      */
1099     @SystemApi
1100     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
setUserSwitchUiCallback(@onNull @allbackExecutor Executor executor, @NonNull UserHandleSwitchUiCallback callback)1101     public void setUserSwitchUiCallback(@NonNull @CallbackExecutor Executor executor,
1102             @NonNull UserHandleSwitchUiCallback callback) {
1103         Preconditions.checkArgument(callback != null, "Null callback");
1104         UserSwitchUiCallbackReceiver userSwitchUiCallbackReceiver =
1105                 new UserSwitchUiCallbackReceiver(callback);
1106         try {
1107             mService.setUserSwitchUiCallback(userSwitchUiCallbackReceiver);
1108         } catch (RemoteException e) {
1109             handleRemoteExceptionFromCarService(e);
1110         }
1111     }
1112 
1113     // TODO(b/154958003): use mReceiver instead as now there are two binder objects
1114     /**
1115      * {@code ICarResultReceiver} used to receive user switch UI Callback.
1116      */
1117     private final class UserSwitchUiCallbackReceiver extends ICarResultReceiver.Stub {
1118 
1119         private final UserHandleSwitchUiCallback mUserHandleSwitchUiCallback;
1120 
UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback)1121         UserSwitchUiCallbackReceiver(UserHandleSwitchUiCallback callback) {
1122             mUserHandleSwitchUiCallback = callback;
1123         }
1124 
1125         @Override
send(int userId, Bundle unused)1126         public void send(int userId, Bundle unused) throws RemoteException {
1127             mUserHandleSwitchUiCallback.onUserSwitchStart(UserHandle.of(userId));
1128         }
1129     }
1130 
1131     /**
1132      * {@code ICarResultReceiver} used to receive lifecycle events and dispatch to the proper
1133      * listener.
1134      */
1135     private class LifecycleResultReceiver extends ICarResultReceiver.Stub {
1136         @Override
send(int resultCode, Bundle resultData)1137         public void send(int resultCode, Bundle resultData) {
1138             if (resultData == null) {
1139                 Slog.w(TAG, "Received result (" + resultCode + ") without data");
1140                 return;
1141             }
1142             int from = resultData.getInt(BUNDLE_PARAM_PREVIOUS_USER_ID,
1143                     UserManagerHelper.USER_NULL);
1144             int to = resultCode;
1145             int eventType = resultData.getInt(BUNDLE_PARAM_ACTION);
1146             UserLifecycleEvent event = new UserLifecycleEvent(eventType, from, to);
1147             ArrayMap<UserLifecycleListener, Pair<UserLifecycleEventFilter, Executor>> listeners;
1148             synchronized (mLock) {
1149                 if (mListeners == null) {
1150                     Slog.w(TAG, "No listeners for event " + event);
1151                     return;
1152                 }
1153                 listeners = new ArrayMap<>(mListeners);
1154             }
1155             int size = listeners.size();
1156             EventLogHelper.writeCarUserManagerNotifyLifecycleListener(size, eventType, from, to);
1157             for (int i = 0; i < size; i++) {
1158                 UserLifecycleListener listener = listeners.keyAt(i);
1159                 UserLifecycleEventFilter filter = listeners.valueAt(i).first;
1160                 if (filter != null && !filter.apply(event)) {
1161                     if (DBG) {
1162                         Slog.d(TAG, "Listener " + getLambdaName(listener)
1163                                 + " is skipped for the event " + event + " due to the filter "
1164                                 + filter);
1165                     }
1166                     continue;
1167                 }
1168                 Executor executor = listeners.valueAt(i).second;
1169                 if (DBG) {
1170                     Slog.d(TAG, "Calling " + getLambdaName(listener) + " for event " + event);
1171                 }
1172                 executor.execute(() -> listener.onEvent(event));
1173             }
1174             mNumberReceivedEvents++;
1175             if (VERBOSE) {
1176                 if (mEvents == null) {
1177                     mEvents = new ArrayList<>();
1178                 }
1179                 mEvents.add(event);
1180             }
1181         }
1182     }
1183 
1184     /** @hide */
1185     @Override
onCarDisconnected()1186     public void onCarDisconnected() {
1187         // nothing to do
1188     }
1189 
1190     private final class Dumper implements Dumpable {
1191         @Override
dump(PrintWriter pw, String[] args)1192         public void dump(PrintWriter pw, String[] args) {
1193             String prefix = "  ";
1194 
1195             pw.printf("DBG=%b, VERBOSE=%b\n", DBG, VERBOSE);
1196             int listenersSize = 0;
1197             synchronized (mLock) {
1198                 pw.printf("mReceiver: %s\n", mReceiver);
1199                 if (mListeners == null) {
1200                     pw.println("no listeners");
1201                 } else {
1202                     listenersSize = mListeners.size();
1203                     pw.printf("%d listeners\n", listenersSize);
1204                 }
1205                 if (DBG) {
1206                     for (int i = 0; i < listenersSize; i++) {
1207                         pw.printf("%s%d: %s\n", prefix, i + 1, mListeners.keyAt(i));
1208                     }
1209                 }
1210             }
1211             pw.printf("mNumberReceivedEvents: %d\n", mNumberReceivedEvents);
1212             if (VERBOSE && mEvents != null) {
1213                 for (int i = 0; i < mEvents.size(); i++) {
1214                     pw.printf("%s%d: %s\n", prefix, i + 1, mEvents.get(i));
1215                 }
1216             }
1217         }
1218 
1219         @Override
getDumpableName()1220         public String getDumpableName() {
1221             return CarUserManager.class.getSimpleName();
1222         }
1223     }
1224 
1225     /**
1226      * @hide
1227      */
1228     @SystemApi
1229     @NonNull
lifecycleEventTypeToString(@serLifecycleEventType int type)1230     public static String lifecycleEventTypeToString(@UserLifecycleEventType int type) {
1231         switch (type) {
1232             case USER_LIFECYCLE_EVENT_TYPE_STARTING:
1233                 return "STARTING";
1234             case USER_LIFECYCLE_EVENT_TYPE_SWITCHING:
1235                 return "SWITCHING";
1236             case USER_LIFECYCLE_EVENT_TYPE_UNLOCKING:
1237                 return "UNLOCKING";
1238             case USER_LIFECYCLE_EVENT_TYPE_UNLOCKED:
1239                 return "UNLOCKED";
1240             case USER_LIFECYCLE_EVENT_TYPE_STOPPING:
1241                 return "STOPPING";
1242             case USER_LIFECYCLE_EVENT_TYPE_STOPPED:
1243                 return "STOPPED";
1244             case USER_LIFECYCLE_EVENT_TYPE_POST_UNLOCKED:
1245                 return "POST_UNLOCKED";
1246             case USER_LIFECYCLE_EVENT_TYPE_CREATED:
1247                 return "CREATED";
1248             case USER_LIFECYCLE_EVENT_TYPE_REMOVED:
1249                 return "REMOVED";
1250             case USER_LIFECYCLE_EVENT_TYPE_VISIBLE:
1251                 return "VISIBLE";
1252             case USER_LIFECYCLE_EVENT_TYPE_INVISIBLE:
1253                 return "INVISIBLE";
1254             default:
1255                 return "UNKNOWN-" + type;
1256         }
1257     }
1258 
1259     /**
1260      * Checks if the given {@code userId} represents a valid user.
1261      *
1262      * <p>A "valid" user:
1263      *
1264      * <ul>
1265      *   <li>Must exist in the device.
1266      *   <li>Is not in the process of being deleted.
1267      *   <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use
1268      *   {@link UserManager#isHeadlessSystemUserMode() headless system user mode}.
1269      * </ul>
1270      *
1271      * @hide
1272      * @deprecated use {@link #isValidUser(UserHandle)} instead.
1273      */
1274     @Deprecated
1275     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
1276             android.Manifest.permission.CREATE_USERS})
isValidUser(@serIdInt int userId)1277     public boolean isValidUser(@UserIdInt int userId) {
1278         return isValidUser(UserHandle.of(userId));
1279     }
1280 
1281     /**
1282      * Checks if the given {@code userHandle} represents a valid user.
1283      *
1284      * <p>A "valid" user:
1285      *
1286      * <ul>
1287      *   <li>Must exist in the device.
1288      *   <li>Is not in the process of being deleted.
1289      *   <li>Cannot be the {@link UserHandle#isSystem() system} user on devices that use
1290      *   {@link UserManager#isHeadlessSystemUserMode() headless system user mode}.
1291      * </ul>
1292      *
1293      */
1294     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
1295             android.Manifest.permission.CREATE_USERS})
1296     @SuppressWarnings("UserHandle")
isValidUser(@onNull UserHandle userHandle)1297     public boolean isValidUser(@NonNull UserHandle userHandle) {
1298         List<UserHandle> allUsers = mUserManager.getUserHandles(/* excludeDying=*/ true);
1299         for (int i = 0; i < allUsers.size(); i++) {
1300             UserHandle user = allUsers.get(i);
1301             if (user.equals(userHandle) && (!userHandle.equals(UserHandle.SYSTEM)
1302                     || !mIsHeadlessSystemUserMode)) {
1303                 return true;
1304             }
1305         }
1306         return false;
1307     }
1308 
1309     /**
1310      * Defines a lifecycle event for an Android user.
1311      *
1312      * @hide
1313      */
1314     @SystemApi
1315     public static final class UserLifecycleEvent {
1316         private final @UserLifecycleEventType int mEventType;
1317         private final @UserIdInt int mUserId;
1318         private final @UserIdInt int mPreviousUserId;
1319 
1320         /** @hide */
UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int from, @UserIdInt int to)1321         public UserLifecycleEvent(@UserLifecycleEventType int eventType,
1322                 @UserIdInt int from, @UserIdInt int to) {
1323             mEventType = eventType;
1324             mPreviousUserId = from;
1325             mUserId = to;
1326         }
1327 
1328         /** @hide */
UserLifecycleEvent(@serLifecycleEventType int eventType, @UserIdInt int to)1329         public UserLifecycleEvent(@UserLifecycleEventType int eventType, @UserIdInt int to) {
1330             this(eventType, UserManagerHelper.USER_NULL, to);
1331         }
1332 
1333         /**
1334          * Gets the event type.
1335          *
1336          * @return either {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STARTING},
1337          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING},
1338          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKING},
1339          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKED},
1340          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPING} or
1341          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPED} for all apps;
1342          * for apps {@link CarPackageManager#getTargetCarVersion() targeting car version}
1343          * {@link CarVersion.VERSION_CODES#TIRAMISU_1} or higher, it could be new types
1344          * added on later releases, such as
1345          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_CREATED},
1346          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_REMOVED} and possibly others.
1347          *
1348          */
1349         @UserLifecycleEventType
getEventType()1350         public int getEventType() {
1351             return mEventType;
1352         }
1353 
1354         /**
1355          * Gets the id of the user whose event is being reported.
1356          *
1357          * @hide
1358          */
1359         @UserIdInt
getUserId()1360         public int getUserId() {
1361             return mUserId;
1362         }
1363 
1364         /**
1365          * Gets the handle of the user whose event is being reported.
1366          */
1367         @NonNull
getUserHandle()1368         public UserHandle getUserHandle() {
1369             return UserHandle.of(mUserId);
1370         }
1371 
1372         /**
1373          * Gets the id of the user being switched from.
1374          *
1375          * <p>This method returns {@link UserHandle#USER_NULL} for all event types but
1376          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}.
1377          *
1378          * @hide
1379          */
1380         @UserIdInt
getPreviousUserId()1381         public int getPreviousUserId() {
1382             return mPreviousUserId;
1383         }
1384 
1385         /**
1386          * Gets the handle of the user being switched from.
1387          *
1388          * <p>This method returns {@code null} for all event types but
1389          * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING}.
1390          */
1391         @Nullable
getPreviousUserHandle()1392         public UserHandle getPreviousUserHandle() {
1393             return mPreviousUserId == UserManagerHelper.USER_NULL ? null
1394                     : UserHandle.of(mPreviousUserId);
1395         }
1396 
1397         @Override
toString()1398         public String toString() {
1399             StringBuilder builder = new StringBuilder("Event[type=")
1400                     .append(lifecycleEventTypeToString(mEventType));
1401             if (mPreviousUserId != UserManagerHelper.USER_NULL) {
1402                 builder
1403                     .append(",from=").append(mPreviousUserId)
1404                     .append(",to=").append(mUserId);
1405             } else {
1406                 builder.append(",user=").append(mUserId);
1407             }
1408 
1409             return builder.append(']').toString();
1410         }
1411 
1412         @Override
equals(@ullable Object o)1413         public boolean equals(@Nullable Object o) {
1414             if (this == o) return true;
1415             if (o == null || getClass() != o.getClass()) return false;
1416 
1417             UserLifecycleEvent that = (UserLifecycleEvent) o;
1418             return mEventType == that.mEventType && mUserId == that.mUserId
1419                     && mPreviousUserId == that.mPreviousUserId;
1420         }
1421 
1422         @Override
hashCode()1423         public int hashCode() {
1424             int hash = 23;
1425             hash = 17 * hash + mEventType;
1426             hash = 17 * hash + mUserId;
1427             hash = 17 * hash + mPreviousUserId;
1428 
1429             return hash;
1430         }
1431     }
1432 
1433     /**
1434      * Listener for Android User lifecycle events.
1435      *
1436      * <p>Must be registered using {@link CarUserManager#addListener(UserLifecycleListener)} and
1437      * unregistered through {@link CarUserManager#removeListener(UserLifecycleListener)}.
1438      *
1439      * @hide
1440      */
1441     @SystemApi
1442     public interface UserLifecycleListener {
1443 
1444         /**
1445          * Called to notify the given {@code event}.
1446          */
onEvent(@onNull UserLifecycleEvent event)1447         void onEvent(@NonNull UserLifecycleEvent event);
1448     }
1449 
1450     /**
1451      * Callback for notifying user switch before switch started.
1452      *
1453      * <p> It should only be used by Car System UI. The purpose of this callback is to notify the
1454      * Car System UI to display the user switch UI.
1455      *
1456      * @hide
1457      * @deprecated use {@link #UserHandleSwitchUiCallback} instead.
1458      */
1459     @Deprecated
1460     public interface UserSwitchUiCallback {
1461 
1462         /**
1463          * Called to notify that user switch dialog should be shown now.
1464          */
showUserSwitchDialog(@serIdInt int userId)1465         void showUserSwitchDialog(@UserIdInt int userId);
1466     }
1467 
1468     /**
1469      * Callback for notifying user switch before switch started.
1470      *
1471      * @hide
1472      */
1473     @SystemApi
1474     public interface UserHandleSwitchUiCallback {
1475 
1476         /**
1477          * Called before the user switch starts.
1478          *
1479          * <p> This is typically used to show the user dialog.
1480          */
1481         @SuppressWarnings("UserHandleName")
onUserSwitchStart(@onNull UserHandle userHandle)1482         void onUserSwitchStart(@NonNull UserHandle userHandle);
1483     }
1484 }
1485