1 /*
2  * Copyright (C) 2020 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 android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.RequiresPermission;
22 import android.annotation.UserIdInt;
23 import android.car.Car;
24 import android.car.CarManagerBase;
25 import android.car.ICarUserService;
26 import android.car.annotation.ExperimentalFeature;
27 import android.content.pm.UserInfo;
28 import android.os.RemoteException;
29 import android.os.UserHandle;
30 import android.util.Log;
31 
32 import com.android.internal.infra.AndroidFuture;
33 
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.List;
37 
38 /**
39  * Temporary class containing {@link CarUserManager} features that are not ready yet.
40  *
41  * <p>New instances are created through {@link #from(CarUserManager)}.
42  *
43  * @hide
44  */
45 @ExperimentalFeature
46 public final class ExperimentalCarUserManager extends CarManagerBase {
47 
48     private static final String TAG = ExperimentalCarUserManager.class.getSimpleName();
49 
50     /**
51      *  User id representing invalid user.
52      */
53     private static final int INVALID_USER_ID = UserHandle.USER_NULL;
54 
55     private final ICarUserService mService;
56 
57     /**
58      * Factory method to create a new instance.
59      */
from(@onNull CarUserManager carUserManager)60     public static ExperimentalCarUserManager from(@NonNull CarUserManager carUserManager) {
61         return carUserManager.newExperimentalCarUserManager();
62     }
63 
ExperimentalCarUserManager(@onNull Car car, @NonNull ICarUserService service)64     ExperimentalCarUserManager(@NonNull Car car, @NonNull ICarUserService service) {
65         super(car);
66 
67         mService = service;
68     }
69 
70     /**
71      * Creates a driver who is a regular user and is allowed to login to the driving occupant zone.
72      *
73      * @param name The name of the driver to be created.
74      * @param admin Whether the created driver will be an admin.
75      * @return an {@link AndroidFuture} that can be used to track operation's completion and
76      *         retrieve its result (if any).
77      *
78      * @hide
79      */
80     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
createDriver(@onNull String name, boolean admin)81     public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
82         try {
83             return mService.createDriver(name, admin);
84         } catch (RemoteException e) {
85             AndroidFuture<UserCreationResult> future = new AndroidFuture<>();
86             future.complete(new UserCreationResult(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE));
87             handleRemoteExceptionFromCarService(e);
88             return future;
89         }
90     }
91 
92     /**
93      * Creates a passenger who is a profile of the given driver.
94      *
95      * @param name The name of the passenger to be created.
96      * @param driverId User id of the driver under whom a passenger is created.
97      * @return user id of the created passenger, or {@code INVALID_USER_ID} if the passenger
98      *         could not be created.
99      *
100      * @hide
101      */
102     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
103     @Nullable
createPassenger(@onNull String name, @UserIdInt int driverId)104     public int createPassenger(@NonNull String name, @UserIdInt int driverId) {
105         try {
106             UserInfo ui = mService.createPassenger(name, driverId);
107             return ui != null ? ui.id : INVALID_USER_ID;
108         } catch (RemoteException e) {
109             return handleRemoteExceptionFromCarService(e, null);
110         }
111     }
112 
113     /**
114      * Switches a driver to the given user.
115      *
116      * @param driverId User id of the driver to switch to.
117      * @return an {@link AndroidFuture} that can be used to track operation's completion and
118      *         retrieve its result (if any).
119      *
120      * @hide
121      */
122     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
switchDriver(@serIdInt int driverId)123     public AndroidFuture<UserSwitchResult> switchDriver(@UserIdInt int driverId) {
124         try {
125             AndroidFuture<UserSwitchResult> future = new AndroidFuture<>() {
126                 @Override
127                 protected void onCompleted(UserSwitchResult result, Throwable err) {
128                     if (result == null) {
129                         Log.w(TAG, "switchDriver(" + driverId + ") failed: " + err);
130                     }
131                     super.onCompleted(result, err);
132                 }
133             };
134             mService.switchDriver(driverId, future);
135             return future;
136         } catch (RemoteException e) {
137             AndroidFuture<UserSwitchResult> future = new AndroidFuture<>();
138             future.complete(
139                     new UserSwitchResult(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE, null));
140             handleRemoteExceptionFromCarService(e);
141             return future;
142         }
143     }
144 
145     /**
146      * Returns all drivers who can occupy the driving zone. Guest users are included in the list.
147      *
148      * @return the list of user ids who can be a driver on the device.
149      *
150      * @hide
151      */
152     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
153     @NonNull
getAllDrivers()154     public List<Integer> getAllDrivers() {
155         try {
156             return getUserIdsFromUserInfos(mService.getAllDrivers());
157         } catch (RemoteException e) {
158             return handleRemoteExceptionFromCarService(e, Collections.emptyList());
159         }
160     }
161 
162     /**
163      * Returns all passengers under the given driver.
164      *
165      * @param driverId User id of a driver.
166      * @return the list of user ids who are passengers under the given driver.
167      *
168      * @hide
169      */
170     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
171     @NonNull
getPassengers(@serIdInt int driverId)172     public List<Integer> getPassengers(@UserIdInt int driverId) {
173         try {
174             return getUserIdsFromUserInfos(mService.getPassengers(driverId));
175         } catch (RemoteException e) {
176             return handleRemoteExceptionFromCarService(e, Collections.emptyList());
177         }
178     }
179 
180     /**
181      * Assigns the passenger to the zone and starts the user if it is not started yet.
182      *
183      * @param passengerId User id of the passenger to be started.
184      * @param zoneId Zone id to which the passenger is assigned.
185      * @return {@code true} if the user is successfully started or the user is already running.
186      *         Otherwise, {@code false}.
187      *
188      * @hide
189      */
190     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
startPassenger(@serIdInt int passengerId, int zoneId)191     public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
192         try {
193             return mService.startPassenger(passengerId, zoneId);
194         } catch (RemoteException e) {
195             return handleRemoteExceptionFromCarService(e, false);
196         }
197     }
198 
199     /**
200      * Stops the given passenger.
201      *
202      * @param passengerId User id of the passenger to be stopped.
203      * @return {@code true} if successfully stopped, or {@code false} if failed.
204      *
205      * @hide
206      */
207     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
stopPassenger(@serIdInt int passengerId)208     public boolean stopPassenger(@UserIdInt int passengerId) {
209         try {
210             return mService.stopPassenger(passengerId);
211         } catch (RemoteException e) {
212             return handleRemoteExceptionFromCarService(e, false);
213         }
214     }
215 
216     /** @hide */
217     @Override
onCarDisconnected()218     public void onCarDisconnected() {
219         // nothing to do
220     }
221 
getUserIdsFromUserInfos(List<UserInfo> infos)222     private List<Integer> getUserIdsFromUserInfos(List<UserInfo> infos) {
223         List<Integer> ids = new ArrayList<>(infos.size());
224         for (UserInfo ui : infos) {
225             ids.add(ui.id);
226         }
227         return ids;
228     }
229 }
230