Propiedades HAL de usuario

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 actuales de hardware y energía, muchas ECU se encienden antes de que se encienda el sistema de infoentretenimiento 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, Android Automotive OS (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 le indica a la HAL qué usuario de Android debe iniciar el infoentretenimiento, lo que reduce el tiempo que un conductor espera a que se cargue su usuario de Android.

Habilitar el usuario HAL

Las propiedades de HAL del usuario deben habilitarse explícitamente asegurándose de que la propiedad del sistema android.car.user_hal_enabled esté establecida 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 descargando UserHalService :

$ adb shell dumpsys car_service --hal UserHalService|grep enabled
user_hal_enabled=true

También puede 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 de 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 de usuario

Propiedades del ciclo de vida del usuario

Las siguientes propiedades proporcionan la 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 User HAL, se deben implementar todas las siguientes propiedades.

HAL Propiedad Descripción
INITIAL_USER_INFO
(LEER ESCRIBIR)
El sistema Android llama a esta propiedad para determinar qué usuario de Android iniciará el sistema cuando el dispositivo arranque o se reanude desde Suspender a RAM (STR). Cuando se le llama, el HAL debe responder con una de estas opciones:
  • El comportamiento predeterminado establecido por Android (cambiar al último usuario utilizado o crear un nuevo usuario si este es el primer arranque).
  • Cambiar a un usuario existente.
  • Cree un nuevo usuario (con las propiedades opcionales de nombre, indicadores, configuración regional del sistema, etc.) y cambie a ese nuevo usuario.

Nota: si HAL no responde, el comportamiento predeterminado es ejecutarse después de un período de tiempo de espera (cinco (5) segundos de forma predeterminada), lo que retrasa el arranque. Si HAL responde, pero el sistema Android no puede ejecutar la acción (por ejemplo, si se ha alcanzado el número máximo de usuarios), se utiliza el comportamiento predeterminado.

Por ejemplo, de forma predeterminada, el sistema Android se inicia en el último usuario activo al iniciarse. 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 específico.

SWITCH_USER
(LEER ESCRIBIR)
Se llama a esta propiedad cuando se cambia el usuario de Android activo en primer plano. El sistema Android o HAL pueden llamar a la propiedad para solicitar un cambio de usuario. Los tres flujos de trabajo son:
  • Moderno. Switch iniciado desde CarUserManager .
  • Legado. Cambio iniciado desde ActivityManager .
  • Vehículo. Llamado por el HAL para solicitar un cambio de usuario.

El flujo de trabajo moderno utiliza un enfoque de compromiso de dos fases para garantizar que el sistema Android y la ECU externa estén sincronizados. Cuando Android inicia el cambio:

  1. Compruebe la HAL para determinar si se puede cambiar de usuario.

    El HAL responde con SUCCESS o FAILURE , para que Android sepa si continuar o no.

  2. Complete el cambio de usuario de Android.

    Android envía una respuesta ANDROID_POST_SWITCH a la HAL para indicar el éxito o la falla del cambio.

HAL debe esperar hasta después de la respuesta de ANDROID_POST_SWITCH para actualizar su estado para sincronizar ECU o actualizar otras propiedades de HAL.

Por 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 moverá durante el cambio de usuario. Por lo tanto, la ECU que controla los asientos no confirma el cambio, HAL responde con una falla y el usuario de Android no se 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 a ActivityManager.switchUser() en lugar de CarUserManager.switchUser() . Las aplicaciones de Settings y SystemUI de referencia ya usan esta última, pero si un OEM proporciona sus propias aplicaciones de configuración para cambiar de usuario, los OEM deben cambiar el uso.

Por ejemplo, si una aplicación utiliza ActivityManager.switchUser() para cambiar de usuario, se envía una llamada unidireccional a la HAL para informar que se ha producido un cambio de usuario.

El flujo de trabajo del vehículo se origina en HAL, no en el sistema Android:

  1. La HAL solicita un cambio de usuario.
  2. El sistema completa el cambio de usuario de Android.
  3. Android envía una respuesta ANDROID_POST_SWITCH a la HAL para indicar el éxito o la falla del cambio.

Por ejemplo , Bob usó el llavero de Alice para abrir el auto y HAL respondió a la solicitud INITIAL_USER_INFO con la ID de usuario de Alice. A continuación, una ECU de sensor biométrico identificó al conductor como Bob, por lo que el usuario HAL envió una solicitud SWITCH_USER para cambiar de usuario.

CREATE_USER
(LEER ESCRIBIR)
El sistema Android llama a esta propiedad cuando se crea un nuevo usuario de Android (usando la API CarUserManager.createUser() ).

El HAL responde con SUCCESS o FAILURE . Si HAL responde con una falla, el sistema Android elimina al usuario.

Por ejemplo, un conductor toca un icono de la interfaz de usuario de infoentretenimiento para crear un nuevo usuario de Android. Este envía una solicitud al HAL y al resto de subsistemas del vehículo. Las ECU son informadas del Usuario recién creado. Luego, otros subsistemas y ECU asocian su ID de usuario interno con la ID de usuario de Android.

REMOVE_USER
(Escribir solamente)
El sistema Android llama a esta propiedad después de eliminar un usuario de Android (con la API CarUserManager.removeUser() ).

Esta es una llamada unidireccional: no se espera respuesta de la HAL.

Por 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 y ECU del vehículo sobre la eliminación del usuario para que puedan eliminar su identificación de usuario interna.

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 HAL de usuario.

HAL Propiedad 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.

Por ejemplo, un conductor toca un ícono de la interfaz de usuario de infoentretenimiento para asociar el llavero usado para abrir el vehículo (KEY_123) con el usuario de Android activo actual (USER_11).

Bibliotecas auxiliares

Todos los objetos usados ​​en los mensajes de solicitud y respuesta (como UserInfo , InitialUserInfoRequest , InitialUSerInfoResponse , etc.) tienen una representación de alto nivel usando la struct de C++, pero la eliminación debe aplanarse en objetos VehiclePropValue estándar (vea los ejemplos a continuación). Para facilitar el desarrollo, se proporciona una biblioteca auxiliar de C++ en AOSP para convertir automáticamente las structs HAL del usuario en un 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:

flujo de trabajo

Figura 1. Flujo de trabajo de propiedades de HAL de 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 generalmente ocurre cuando un cambio de Android tiene éxito:

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 generalmente ocurre cuando falla un cambio 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 de flujo de trabajo heredado

Esta respuesta generalmente ocurre cuando un cambio de Android tiene éxito:

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
}

REMOVE_USER

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)
}

USUARIO_IDENTIFICACIÓN_ASOCIACIÓN

Establecer ejemplo (llavero electrónico asociado con el 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
}