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 null, null)); 88 handleRemoteExceptionFromCarService(e); 89 return future; 90 } 91 } 92 93 /** 94 * Creates a passenger who is a profile of the given driver. 95 * 96 * @param name The name of the passenger to be created. 97 * @param driverId User id of the driver under whom a passenger is created. 98 * @return user id of the created passenger, or {@code INVALID_USER_ID} if the passenger 99 * could not be created. 100 * 101 * @hide 102 */ 103 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) 104 @Nullable createPassenger(@onNull String name, @UserIdInt int driverId)105 public int createPassenger(@NonNull String name, @UserIdInt int driverId) { 106 try { 107 UserInfo ui = mService.createPassenger(name, driverId); 108 return ui != null ? ui.id : INVALID_USER_ID; 109 } catch (RemoteException e) { 110 return handleRemoteExceptionFromCarService(e, null); 111 } 112 } 113 114 /** 115 * Switches a driver to the given user. 116 * 117 * @param driverId User id of the driver to switch to. 118 * @return an {@link AndroidFuture} that can be used to track operation's completion and 119 * retrieve its result (if any). 120 * 121 * @hide 122 */ 123 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) switchDriver(@serIdInt int driverId)124 public AndroidFuture<UserSwitchResult> switchDriver(@UserIdInt int driverId) { 125 try { 126 AndroidFuture<UserSwitchResult> future = new AndroidFuture<>() { 127 @Override 128 protected void onCompleted(UserSwitchResult result, Throwable err) { 129 if (result == null) { 130 Log.w(TAG, "switchDriver(" + driverId + ") failed: " + err); 131 } 132 super.onCompleted(result, err); 133 } 134 }; 135 mService.switchDriver(driverId, future); 136 return future; 137 } catch (RemoteException e) { 138 AndroidFuture<UserSwitchResult> future = new AndroidFuture<>(); 139 future.complete( 140 new UserSwitchResult(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE, null)); 141 handleRemoteExceptionFromCarService(e); 142 return future; 143 } 144 } 145 146 /** 147 * Returns all drivers who can occupy the driving zone. Guest users are included in the list. 148 * 149 * @return the list of user ids who can be a driver on the device. 150 * 151 * @hide 152 */ 153 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) 154 @NonNull getAllDrivers()155 public List<Integer> getAllDrivers() { 156 try { 157 return getUserIdsFromUserInfos(mService.getAllDrivers()); 158 } catch (RemoteException e) { 159 return handleRemoteExceptionFromCarService(e, Collections.emptyList()); 160 } 161 } 162 163 /** 164 * Returns all passengers under the given driver. 165 * 166 * @param driverId User id of a driver. 167 * @return the list of user ids who are passengers under the given driver. 168 * 169 * @hide 170 */ 171 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) 172 @NonNull getPassengers(@serIdInt int driverId)173 public List<Integer> getPassengers(@UserIdInt int driverId) { 174 try { 175 return getUserIdsFromUserInfos(mService.getPassengers(driverId)); 176 } catch (RemoteException e) { 177 return handleRemoteExceptionFromCarService(e, Collections.emptyList()); 178 } 179 } 180 181 /** 182 * Assigns the passenger to the zone and starts the user if it is not started yet. 183 * 184 * @param passengerId User id of the passenger to be started. 185 * @param zoneId Zone id to which the passenger is assigned. 186 * @return {@code true} if the user is successfully started or the user is already running. 187 * Otherwise, {@code false}. 188 * 189 * @hide 190 */ 191 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) startPassenger(@serIdInt int passengerId, int zoneId)192 public boolean startPassenger(@UserIdInt int passengerId, int zoneId) { 193 try { 194 return mService.startPassenger(passengerId, zoneId); 195 } catch (RemoteException e) { 196 return handleRemoteExceptionFromCarService(e, false); 197 } 198 } 199 200 /** 201 * Stops the given passenger. 202 * 203 * @param passengerId User id of the passenger to be stopped. 204 * @return {@code true} if successfully stopped, or {@code false} if failed. 205 * 206 * @hide 207 */ 208 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) stopPassenger(@serIdInt int passengerId)209 public boolean stopPassenger(@UserIdInt int passengerId) { 210 try { 211 return mService.stopPassenger(passengerId); 212 } catch (RemoteException e) { 213 return handleRemoteExceptionFromCarService(e, false); 214 } 215 } 216 217 /** @hide */ 218 @Override onCarDisconnected()219 public void onCarDisconnected() { 220 // nothing to do 221 } 222 getUserIdsFromUserInfos(List<UserInfo> infos)223 private List<Integer> getUserIdsFromUserInfos(List<UserInfo> infos) { 224 List<Integer> ids = new ArrayList<>(infos.size()); 225 for (UserInfo ui : infos) { 226 ids.add(ui.id); 227 } 228 return ids; 229 } 230 } 231