blob: fa7eb7234deac8eebe333c5fe0b8054e52e3af62 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.car.user;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.car.Car;
import android.car.CarManagerBase;
import android.car.ICarUserService;
import android.car.annotation.ExperimentalFeature;
import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.infra.AndroidFuture;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Temporary class containing {@link CarUserManager} features that are not ready yet.
*
* <p>New instances are created through {@link #from(CarUserManager)}.
*
* @hide
*/
@ExperimentalFeature
public final class ExperimentalCarUserManager extends CarManagerBase {
private static final String TAG = ExperimentalCarUserManager.class.getSimpleName();
/**
* User id representing invalid user.
*/
private static final int INVALID_USER_ID = UserHandle.USER_NULL;
private final ICarUserService mService;
/**
* Factory method to create a new instance.
*/
public static ExperimentalCarUserManager from(@NonNull CarUserManager carUserManager) {
return carUserManager.newExperimentalCarUserManager();
}
ExperimentalCarUserManager(@NonNull Car car, @NonNull ICarUserService service) {
super(car);
mService = service;
}
/**
* Creates a driver who is a regular user and is allowed to login to the driving occupant zone.
*
* @param name The name of the driver to be created.
* @param admin Whether the created driver will be an admin.
* @return an {@link AndroidFuture} that can be used to track operation's completion and
* retrieve its result (if any).
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public AndroidFuture<UserCreationResult> createDriver(@NonNull String name, boolean admin) {
try {
return mService.createDriver(name, admin);
} catch (RemoteException e) {
AndroidFuture<UserCreationResult> future = new AndroidFuture<>();
future.complete(new UserCreationResult(UserCreationResult.STATUS_HAL_INTERNAL_FAILURE,
null, null));
handleRemoteExceptionFromCarService(e);
return future;
}
}
/**
* Creates a passenger who is a profile of the given driver.
*
* @param name The name of the passenger to be created.
* @param driverId User id of the driver under whom a passenger is created.
* @return user id of the created passenger, or {@code INVALID_USER_ID} if the passenger
* could not be created.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@Nullable
public int createPassenger(@NonNull String name, @UserIdInt int driverId) {
try {
UserInfo ui = mService.createPassenger(name, driverId);
return ui != null ? ui.id : INVALID_USER_ID;
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, null);
}
}
/**
* Switches a driver to the given user.
*
* @param driverId User id of the driver to switch to.
* @return an {@link AndroidFuture} that can be used to track operation's completion and
* retrieve its result (if any).
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public AndroidFuture<UserSwitchResult> switchDriver(@UserIdInt int driverId) {
try {
AndroidFuture<UserSwitchResult> future = new AndroidFuture<>() {
@Override
protected void onCompleted(UserSwitchResult result, Throwable err) {
if (result == null) {
Log.w(TAG, "switchDriver(" + driverId + ") failed: " + err);
}
super.onCompleted(result, err);
}
};
mService.switchDriver(driverId, future);
return future;
} catch (RemoteException e) {
AndroidFuture<UserSwitchResult> future = new AndroidFuture<>();
future.complete(
new UserSwitchResult(UserSwitchResult.STATUS_HAL_INTERNAL_FAILURE, null));
handleRemoteExceptionFromCarService(e);
return future;
}
}
/**
* Returns all drivers who can occupy the driving zone. Guest users are included in the list.
*
* @return the list of user ids who can be a driver on the device.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@NonNull
public List<Integer> getAllDrivers() {
try {
return getUserIdsFromUserInfos(mService.getAllDrivers());
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, Collections.emptyList());
}
}
/**
* Returns all passengers under the given driver.
*
* @param driverId User id of a driver.
* @return the list of user ids who are passengers under the given driver.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
@NonNull
public List<Integer> getPassengers(@UserIdInt int driverId) {
try {
return getUserIdsFromUserInfos(mService.getPassengers(driverId));
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, Collections.emptyList());
}
}
/**
* Assigns the passenger to the zone and starts the user if it is not started yet.
*
* @param passengerId User id of the passenger to be started.
* @param zoneId Zone id to which the passenger is assigned.
* @return {@code true} if the user is successfully started or the user is already running.
* Otherwise, {@code false}.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public boolean startPassenger(@UserIdInt int passengerId, int zoneId) {
try {
return mService.startPassenger(passengerId, zoneId);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, false);
}
}
/**
* Stops the given passenger.
*
* @param passengerId User id of the passenger to be stopped.
* @return {@code true} if successfully stopped, or {@code false} if failed.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public boolean stopPassenger(@UserIdInt int passengerId) {
try {
return mService.stopPassenger(passengerId);
} catch (RemoteException e) {
return handleRemoteExceptionFromCarService(e, false);
}
}
/** @hide */
@Override
public void onCarDisconnected() {
// nothing to do
}
private List<Integer> getUserIdsFromUserInfos(List<UserInfo> infos) {
List<Integer> ids = new ArrayList<>(infos.size());
for (UserInfo ui : infos) {
ids.add(ui.id);
}
return ids;
}
}