Muchas arquitecturas de vehículos actuales contienen múltiples unidades de control electrónico (ECU) fuera del sistema de información y entretenimiento que controlan la ergonomía, como la configuración de los asientos y los ajustes de los espejos. Según las arquitecturas de energía y hardware actuales, muchas ECU se encienden antes de que se encienda el sistema de información y entretenimiento basado en Android. Estas ECU pueden interactuar con un sistema de información y entretenimiento basado en Android a través de la capa de abstracción de hardware del vehículo (VHAL) .
A partir de Android 11, el sistema operativo Android Automotive (AAOS) introdujo un nuevo conjunto de propiedades en VHAL para crear, cambiar, eliminar y asociar accesorios externos para identificar a los usuarios. Por ejemplo, estas nuevas propiedades permiten a un conductor vincular un accesorio externo, como un llavero, a su usuario de Android. Luego, cuando el conductor se acerca al vehículo, una ECU se activa y detecta el llavero. Esta ECU indica al HAL qué usuario de Android debe iniciar el sistema de infoentretenimiento, lo que reduce el tiempo que un conductor espera a que se cargue su usuario de Android.
Habilitar el usuario HAL
Las propiedades HAL del usuario deben habilitarse explícitamente asegurándose de que la propiedad del sistema android.car.user_hal_enabled
esté configurada en true
. (Esto también se puede hacer en el archivo car.mk
, por lo que no es necesario configurarlo manualmente). Verifique que user_hal_enabled=true
esté habilitado volcando UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
También puedes verificar user_hal_enabled
usando adb shell getprop android.car.user_hal_enabled
o adb logcat CarServiceHelper *:s
. Si la propiedad está deshabilitada, se muestra un mensaje como el siguiente cuando se inicia system_server
:
I CarServiceHelper: Not using User HAL
Para habilitar manualmente user_hal_enabled
, configure la propiedad del sistema android.car.user_hal_enabled
y reinicie system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
La salida logcat
aparece de la siguiente manera:
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
Propiedades HAL del usuario
Propiedades del ciclo de vida del usuario
Las siguientes propiedades proporcionan información HAL para los estados del ciclo de vida del usuario, que permiten la sincronización del ciclo de vida del usuario entre el sistema Android y una ECU externa. Estas propiedades utilizan un protocolo de solicitud y respuesta, en el que el sistema Android realiza una solicitud estableciendo un valor de propiedad y HAL responde emitiendo un evento de cambio de propiedad.
Nota: Cuando se admite el usuario HAL, se deben implementar todas las propiedades siguientes.
propiedad hal | Descripción |
---|---|
INITIAL_USER_INFO (LEER ESCRIBIR) | El sistema Android llama a esta propiedad para determinar qué usuario de Android inicia el sistema cuando el dispositivo arranca o se reanuda desde Suspend-to-RAM (STR). Cuando se le llama, el HAL debe responder con una de estas opciones:
Nota: Si HAL no responde, el comportamiento predeterminado es ejecutar después de un período de tiempo de espera (cinco segundos de forma predeterminada), lo que retrasa el inicio. Si HAL responde, pero el sistema Android no puede ejecutar la acción (por ejemplo, si se alcanzó el número máximo de usuarios), se utiliza el comportamiento predeterminado. Ejemplo: de forma predeterminada, el sistema Android se inicia con el último usuario activo al iniciar. Si se detecta un llavero para un usuario diferente, la ECU anula la propiedad HAL y, durante el inicio, el sistema Android cambia para iniciarse en ese usuario especificado. |
SWITCH_USER (LEER ESCRIBIR) | Esta propiedad se llama al cambiar el usuario de Android activo en primer plano. La propiedad puede ser llamada por el sistema Android o por HAL para solicitar un cambio de usuario. Los tres flujos de trabajo son:
El flujo de trabajo moderno utiliza un enfoque de confirmación de dos fases para garantizar que el sistema Android y la ECU externa estén sincronizados. Cuando Android inicia el cambio:
HAL debe esperar hasta después de la respuesta Ejemplo: mientras está en movimiento, un conductor intenta cambiar de usuario de Android en la interfaz de usuario de infoentretenimiento. Sin embargo, debido a que la configuración del asiento para el automóvil está vinculada al usuario de Android, el asiento se mueve durante el cambio de usuario. Por lo tanto, la ECU que controla los asientos no confirma el cambio, el HAL responde con un fallo y el usuario de Android no cambia. El flujo de trabajo heredado es una llamada unidireccional enviada después de que se cambia el usuario (por lo que HAL no puede bloquear el cambio). Solo se llama en el arranque (después del cambio de usuario inicial) o para aplicaciones que llaman Ejemplo: si una aplicación usa El flujo de trabajo del vehículo se origina en HAL, no en el sistema Android:
Ejemplo: Bob usó el llavero de Alice para abrir el auto y HAL respondió a la solicitud |
CREATE_USER (LEER ESCRIBIR) | El sistema Android llama a esta propiedad cuando se crea un nuevo usuario de Android (utilizando la API CarUserManager.createUser() ). El HAL responde con Ejemplo: un conductor toca un ícono de la interfaz de usuario de infoentretenimiento para crear un nuevo usuario de Android. Esto envía una solicitud al HAL y al resto de subsistemas del vehículo. Se informa a las ECU del usuario recién creado. Luego, otros subsistemas y ECU asocian su ID de usuario interno con el ID de usuario de Android. |
REMOVE_USER (Escribir solamente) | El sistema Android llama a esta propiedad después de que se elimina un usuario de Android (con el método CarUserManager.removeUser() ).Esta es una llamada unidireccional: no se espera respuesta de HAL. Ejemplo: un conductor toca para eliminar un usuario de Android existente en la interfaz de usuario de infoentretenimiento. Se informa al HAL y a otros subsistemas del vehículo y ECU de la eliminación del Usuario para que puedan eliminar su ID de usuario interno. |
Propiedades adicionales
Las siguientes son propiedades adicionales, no relacionadas con los estados del ciclo de vida del usuario. Cada uno se puede implementar sin admitir el usuario HAL.
Propiedad HAL | Descripción |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LEER ESCRIBIR) | Utilice esta propiedad para asociar cualquier usuario de Android con un mecanismo de identificación, como un llavero o un teléfono. Utilice esta misma propiedad para get o set asociaciones. Ejemplo: un conductor toca un ícono de interfaz de usuario de infoentretenimiento para asociar el llavero utilizado para abrir el vehículo ( |
Bibliotecas auxiliares
Todos los objetos utilizados en los mensajes de solicitud y respuesta (como UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
, etc.) tienen una representación de alto nivel usando struct
C++, pero la eliminación se debe aplanar en objetos VehiclePropValue
estándar (consulte los ejemplos a continuación). Para facilitar el desarrollo, se proporciona una biblioteca auxiliar de C++ en AOSP para convertir automáticamente structs
HAL de usuario en VehiclePropValue
(y viceversa).
Ejemplos
INITIAL_USER_INFO
Ejemplo de solicitud (en el primer arranque)
VehiclePropValue { // flattened from InitialUserInfoRequest prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID [1] = 1 // InitialUserInfoRequestType.FIRST_BOOT [2] = 0 // user id of current user [3] = 1 // flags of current user (SYSTEM) [4] = 1 // number of existing users [5] = 0 // existingUser[0].id [6] = 1 // existingUser[0].flags }
Ejemplo de respuesta (crear usuario administrador)
VehiclePropValue { // flattened from InitialUserInfoResponse prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID (must match request) [1] = 2 // InitialUserInfoResponseAction.CREATE [2] = -10000 // user id (not used on CREATE) [3] = 8 // user flags (ADMIN) prop.values.stringValue: "en-US||Car Owner" // User locale and User name }
CAMBIAR DE USUARIO
El nombre real de las clases y propiedades difiere ligeramente, pero el flujo de trabajo general es el mismo, como se ilustra a continuación:
Figura 1. Flujo de trabajo de propiedades HAL del usuario
Ejemplo de solicitud de flujo de trabajo moderno
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896585 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID [1] = 2 // SwitchUserMessageType::ANDROID_SWITCH ("modern") [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Ejemplo de respuesta de flujo de trabajo moderno
VehiclePropValue { // flattened from SwitchUserResponse prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // SwitchUserMessageType::VEHICLE_RESPONSE [2] = 1 // SwitchUserStatus::SUCCESS }
Ejemplo de respuesta posterior al cambio de flujo de trabajo moderno
Esta respuesta suele ocurrir cuando un cambio de Android se realiza correctamente:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Respuesta posterior al cambio de flujo de trabajo moderno
Esta respuesta suele ocurrir cuando falla un conmutador de Android:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Ejemplo de solicitud de flujo de trabajo heredado
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 2 // Request ID [1] = 1 // SwitchUserMessageType::LEGACY_ANDROID_SWITCH [2,3] = 10,8 // target user id (10) and flags (ADMIN) [4,5] = 0,1 // current user id (0) and flags (SYSTEM) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
Ejemplo de solicitud de flujo de trabajo de vehículos
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must be negative) [1] = 4 // SwitchUserMessageType::VEHICLE_REQUEST [2] = 11 // target user id }
Respuesta posterior al cambio del flujo de trabajo heredado
Esta respuesta suele ocurrir cuando un cambio de Android se realiza correctamente:
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must match from vehicle request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
CREAR USUARIO
Ejemplo de solicitud
VehiclePropValue { // flattened from CreateUserRequest prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,6 // Android id of the created user and flags (id=11, flags=GUEST, EPHEMERAL) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 3 // number of existing users (0, 10, 11) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [10,11] = 11,6 // newUser[2] (id=11, flags=GUEST,EPHEMERAL) }
Ejemplo de respuesta
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
ELIMINAR_USUARIO
Ejemplo de solicitud
VehiclePropValue { // flattened from RemoveUserRequest prop: 299896586 // REMOVE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,0 // Android id of the removed user and flags (none in this case) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 2 // number of existing users (0, 10) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) }
ASOCIACIÓN_IDENTIFICACIÓN_USUARIO
Ejemplo de configuración (llavero asociado al Usuario 10)
VehiclePropValue { // flattened from UserIdentificationSetRequest prop: 299896587 // USER_IDENTIFICATION_ASSOCIATION prop.values.int32Values: [0] = 43 // Request ID [1,2] = 10,0 // Android id (10) and flags (none in this case) [3] = 1 // number of associations being set [4] = 1 // 1st type: UserIdentificationAssociationType::KEY_FOB [5] = 1 // 1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER }