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