HAL de sensores AIDL

La capa de abstracción de hardware (HAL) de sensores es la interfaz entre el framework de sensores de Android y los sensores de un dispositivo, como un acelerómetro o un giroscopio. La HAL de sensores define las funciones que se deben implementar para permitir que el framework controle los sensores.

La HAL de sensores AIDL está disponible en Android 13 y versiones posteriores para dispositivos nuevos y actualizados. La HAL de sensores AIDL, que se basa en la HAL de sensores 2.1, usa la interfaz de la HAL del AIDL y expone el seguimiento de cabeza y los tipos de sensores de IMU de eje limitado.

Interfaz de la HAL del AIDL

La principal fuente de documentación para la HAL de sensores AIDL se encuentra dentro de la definición de HAL en hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

Implementa la HAL de sensores AIDL

Para implementar la HAL de sensores AIDL, un objeto debe extender la ISensors interfaz e implementar todas las funciones definidas en hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.

Inicializa la HAL

El framework de sensores de Android debe inicializar la HAL de sensores antes de que se pueda usar. El framework llama a la función initialize() para proporcionar tres parámetros a la HAL de sensores: dos descriptores de FMQ y un puntero a un objeto ISensorsCallback.

La HAL usa el primer descriptor para crear el FMQ de eventos que se usa para escribir eventos de sensores en el framework. La HAL usa el segundo descriptor para crear el FMQ de bloqueo de activación que se usa para sincronizar cuando la HAL libera su bloqueo de activación para eventos de sensores WAKE_UP. La HAL debe guardar un puntero al objeto ISensorsCallback para que se puedan invocar las funciones de devolución de llamada necesarias.

La función initialize() debe ser la primera función a la que se llame cuando se inicializa la HAL de sensores.

Expón los sensores disponibles

Para obtener una lista de todos los sensores estáticos disponibles en el dispositivo, usa la función getSensorsList(). Esta función muestra una lista de sensores, cada uno identificado de forma única por su controlador. El controlador de un sensor determinado no debe cambiar cuando se reinicia el proceso que aloja la HAL de sensores. Los controladores pueden cambiar en los reinicios del dispositivo y en los reinicios del servidor del sistema.

Si varios sensores comparten el mismo tipo de sensor y la misma propiedad de activación, el primer sensor de la lista se denomina sensor predeterminado y se muestra a las apps que utilizan la función getDefaultSensor(int sensorType, bool wakeUp).

Estabilidad de la lista de sensores

Después de un reinicio de la HAL de sensores, si los datos que muestra getSensorsList() indican un cambio significativo en comparación con la lista de sensores recuperada antes del reinicio, el framework activa un reinicio del tiempo de ejecución de Android. Los cambios significativos en la lista de sensores incluyen casos en los que falta un sensor con un controlador determinado o se modificaron sus atributos, o bien cuando se introducen sensores nuevos. Aunque reiniciar el tiempo de ejecución de Android es perjudicial para el usuario, es necesario porque el framework de Android ya no puede cumplir con el contrato de la API de Android que indica que los sensores estáticos (no dinámicos) no cambian durante la vida útil de una app. Esto también puede impedir que el framework restablezca las solicitudes de sensores activos realizadas por las apps. Por lo tanto, se recomienda a los proveedores de HAL que eviten los cambios innecesarios en la lista de sensores.

Para garantizar controladores de sensores estables, la HAL debe asignar de forma determinista un sensor físico determinado en el dispositivo a su controlador. Aunque la interfaz de la HAL de sensores no exige ninguna implementación específica, los desarrolladores tienen varias opciones disponibles para cumplir con este requisito.

Por ejemplo, la lista de sensores se puede ordenar con una combinación de los atributos fijos de cada sensor, como el proveedor, el modelo y el tipo de sensor. Otra opción se basa en el hecho de que el conjunto de sensores estáticos del dispositivo está fijo en el hardware, por lo que la HAL debe saber cuándo todos los sensores esperados completaron la inicialización antes de mostrar el resultado de getSensorsList(). Esta lista de sensores esperados se puede compilar en el objeto binario de la HAL o almacenarse en un archivo de configuración en el sistema de archivos, y el orden de aparición se puede usar para derivar controladores estables. Aunque la mejor solución depende de los detalles de implementación específicos de tu HAL, el requisito clave es que los controladores de sensores no cambien en los reinicios de la HAL.

Configura los sensores

Antes de activar un sensor, se debe configurar con un período de muestreo y una latencia máxima de informes mediante la función batch().

Un sensor debe poder reconfigurarse en cualquier momento con batch() sin perder datos del sensor.

Período de muestreo

El período de muestreo tiene un significado diferente según el tipo de sensor que se esté configurando:

  • Continuo: Los eventos de sensores se generan a una velocidad continua.
  • En el cambio: Los eventos no se generan más rápido que el período de muestreo y pueden generarse a una velocidad más lenta que el período de muestreo si el valor medido no cambia.
  • Único: Se ignora el período de muestreo.
  • Especial: Para obtener más detalles, consulta Tipos de sensores.

Para obtener información sobre la interacción entre un período de muestreo y los modos de informes de un sensor, consulta Modos de informes.

Latencia máxima de informes

La latencia máxima de informes establece el tiempo máximo en nanosegundos que se pueden retrasar y almacenar los eventos en el FIFO de hardware antes de escribirse en el FMQ de eventos a través de la HAL mientras el SoC está activo.

Un valor de cero indica que los eventos se deben informar en cuanto se midan, ya sea omitiendo el FIFO por completo o vaciándolo en cuanto haya un evento del sensor en el FIFO.

Por ejemplo, un acelerómetro activado a 50 Hz con una latencia máxima de informes de cero activa interrupciones 50 veces por segundo cuando el SoC está activo.

Cuando la latencia máxima de informes es mayor que cero, no es necesario informar los eventos de sensores en cuanto se detectan. Los eventos se pueden almacenar temporalmente en el FIFO de hardware y se pueden informar en lotes, siempre que ningún evento se retrase más que la latencia máxima de informes. Todos los eventos desde el lote anterior se registran y se muestran a la vez. Esto reduce la cantidad de interrupciones enviadas al SoC y permite que el SoC cambie a un modo de menor consumo de energía mientras el sensor captura y agrupa datos.

Cada evento tiene una marca de tiempo asociada. Retrasar el momento en que se informa un evento no debe afectar la marca de tiempo del evento. La marca de tiempo debe ser precisa y corresponder al momento en que ocurrió el evento físicamente, no al momento en que se informó.

Para obtener información y requisitos adicionales sobre cómo informar eventos de sensores con una latencia máxima de informes distinta de cero, consulta Agrupación.

Activa los sensores

El framework habilita y deshabilita los sensores con la función activate(). Antes de activar un sensor, el framework primero debe configurarlo con batch().

Después de desactivar un sensor, no se deben escribir eventos de sensores adicionales de ese sensor en el FMQ de eventos.

Vacía los sensores

Si un sensor está configurado para agrupar datos de sensores, el framework puede forzar un vaciado inmediato de los eventos de sensores agrupados llamando a flush(). Esto hace que los eventos de sensores agrupados para el controlador de sensor especificado se escriban de inmediato en el FMQ de eventos. La HAL de sensores debe agregar un evento de vaciado completo al final de los eventos de sensores que se escriben como resultado de una llamada a flush().

El vaciado se realiza de forma asíncrona (es decir, esta función debe mostrarse de inmediato). Si la implementación usa un solo FIFO para varios sensores, ese FIFO se vacía y el evento de vaciado completo se agrega solo para el sensor especificado.

Si el sensor especificado no tiene FIFO (no es posible el almacenamiento en búfer) o si el FIFO estaba vacío en el momento de la llamada, flush() debe tener éxito y enviar un evento de vaciado completo para ese sensor. Esto se aplica a todos los sensores, excepto a los sensores únicos.

Si se llama a flush() para un sensor único, flush() debe mostrar BAD_VALUE y no generar un evento de vaciado completo.

Escribe eventos de sensores en el FMQ

La HAL de sensores usa el FMQ de eventos para enviar eventos de sensores al framework de sensores de Android.

El FMQ de eventos es un FMQ sincronizado, lo que significa que cualquier intento de escribir más eventos en el FMQ que el espacio disponible permite que se produzca una escritura fallida. En ese caso, la HAL debe determinar si escribir el conjunto actual de eventos como dos grupos de eventos más pequeños o escribir todos los eventos juntos cuando haya suficiente espacio disponible.

Cuando la HAL de sensores haya escrito la cantidad deseada de eventos de sensores en el FMQ de eventos, la HAL de sensores debe notificar al framework que los eventos están listos escribiendo el bit EventQueueFlagBits::READ_AND_PROCESS en la función EventFlag::wake del FMQ de eventos. El EventFlag se puede crear desde el FMQ de eventos con EventFlag::createEventFlag y la función getEventFlagWord() del FMQ de eventos.

La HAL de sensores AIDL admite write y writeBlocking en el FMQ de eventos. La implementación predeterminada proporciona una referencia para usar write. Si se usa la función writeBlocking, la marca readNotification debe establecerse en EventQueueFlagBits::EVENTS_READ, que establece el framework cuando lee eventos del FMQ de eventos. La marca de notificación de escritura debe establecerse en EventQueueFlagBits::READ_AND_PROCESS, que notifica al framework que se escribieron eventos en el FMQ de eventos.

Eventos WAKE_UP

Los eventos WAKE_UP son eventos de sensores que hacen que el procesador de aplicaciones (AP) se active y controle el evento de inmediato. Cada vez que se escribe un evento WAKE_UP en el FMQ de eventos, la HAL de sensores debe proteger un bloqueo de activación para garantizar que el sistema permanezca activo hasta que el framework pueda controlar el evento. Cuando recibe un evento WAKE_UP, el framework protege su propio bloqueo de activación, lo que permite que la HAL de sensores libere su bloqueo de activación. Para sincronizar cuando la HAL de sensores libera su bloqueo de activación, usa el FMQ de bloqueo de activación.

La HAL de sensores debe leer el FMQ de bloqueo de activación para determinar la cantidad de eventos WAKE_UP que controló el framework. La HAL solo debe liberar su bloqueo de activación para eventos WAKE_UP si la cantidad total de eventos WAKE_UP no controlados es cero. Después de controlar los eventos de sensores, el framework cuenta la cantidad de eventos marcados como eventos WAKE_UP y vuelve a escribir este número en el FMQ de bloqueo de activación.

El framework establece la notificación de escritura WakeLockQueueFlagBits::DATA_WRITTEN en el FMQ de bloqueo de activación cada vez que escribe datos en el FMQ de bloqueo de activación.

Sensores dinámicos

Los sensores dinámicos son sensores que no forman parte física del dispositivo, pero que se pueden usar como entrada para el dispositivo, como un gamepad con un acelerómetro.

Cuando se conecta un sensor dinámico, se debe llamar a la función onDynamicSensorConnected en ISensorsCallback desde la HAL de sensores. Esto notifica al framework sobre el nuevo sensor dinámico y permite que el sensor se controle a través del framework y que los clientes consuman los eventos del sensor.

Del mismo modo, cuando se desconecta un sensor dinámico, se debe llamar a la función onDynamicSensorDisconnected en ISensorsCallback para que el framework pueda quitar cualquier sensor que ya no esté disponible.

Canal directo

El canal directo es un método de operación en el que los eventos de sensores se escriben en una memoria específica en lugar de en el FMQ de eventos, lo que omite el framework de sensores de Android. Un cliente que registra un canal directo debe leer los eventos de sensores directamente desde la memoria que se usó para crear el canal directo y no recibirá los eventos de sensores a través del framework. La función configDirectReport() es similar a batch() para el funcionamiento normal y configura el canal de informes directos.

Las funciones registerDirectChannel() y unregisterDirectChannel() crean o destruyen un nuevo canal directo.

Modos de operación

La función setOperationMode() permite que el framework configure un sensor para que el framework pueda insertar datos de sensores en el sensor. Esto es útil para las pruebas, en especial para los algoritmos que existen debajo del framework.

Por lo general, la función injectSensorData() se usa para enviar parámetros operativos a la HAL de sensores. La función también se puede usar para insertar eventos de sensores en un sensor específico.

Validación

Para validar tu implementación de la HAL de sensores, ejecuta las pruebas de CTS y VTS de sensores.

Pruebas de CTS

Las pruebas de CTS de sensores existen en las pruebas de CTS automatizadas y en la app manual del verificador de CTS.

Las pruebas automatizadas se encuentran en cts/tests/sensor/src/android/hardware/cts. Estas pruebas verifican la funcionalidad estándar de los sensores, como la activación de sensores, la agrupación y las tasas de eventos de sensores.

Las pruebas del verificador de CTS se encuentran en cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Estas pruebas requieren la entrada manual del operador de prueba y garantizan que los sensores informen valores precisos.

Aprobar las pruebas de CTS es fundamental para garantizar que el dispositivo en prueba cumpla con todos los requisitos del CDD.

Pruebas de VTS

Las pruebas de VTS para la HAL de sensores AIDL se encuentran en hardware/interfaces/sensors/aidl/vts/. Estas pruebas garantizan que la HAL de sensores se implemente correctamente y que se cumplan todos los requisitos dentro de ISensors.aidl y ISensorsCallback.aidl.

Inicializa la HAL

Se debe admitir la función initialize() para establecer FMQ entre el framework y la HAL.

Expón los sensores disponibles

En la HAL de sensores AIDL, la función getSensorsList() debe mostrar el mismo valor durante un solo inicio del dispositivo, incluso en los reinicios de la HAL de sensores. Un nuevo requisito de la función getSensorsList() es que debe mostrar el mismo valor durante un solo inicio del dispositivo, incluso en los reinicios de la HAL de sensores. Esto permite que el framework intente restablecer las conexiones de sensores si se reinicia el servidor del sistema. El valor que muestra getSensorsList() puede cambiar después de que el dispositivo realice un reinicio.

Escribe eventos de sensores en el FMQ

En lugar de esperar a que se llame a poll(), en la HAL de sensores AIDL, la HAL de sensores debe escribir de forma proactiva eventos de sensores en el FMQ de eventos cada vez que estén disponibles. La HAL también es responsable de escribir los bits correctos en EventFlag para provocar una lectura de FMQ dentro del framework.

Eventos WAKE_UP

En la HAL de sensores 1.0, la HAL podía liberar su bloqueo de activación para cualquier evento WAKE_UP en cualquier llamada posterior a poll() después de que se publicara un WAKE_UP en poll(), ya que esto indicaba que el framework había procesado todos los eventos de sensores y había obtenido un bloqueo de activación, si era necesario. Debido a que, en la HAL de sensores AIDL, ya no se notifica a la HAL cuando el framework procesó los eventos escritos en el FMQ, el FMQ de bloqueo de activación permite que el framework se comunique con la HAL cuando controló eventos WAKE_UP.

En la HAL de sensores AIDL, el bloqueo de activación protegido por la HAL de sensores para eventos WAKE_UP debe comenzar con SensorsHAL_WAKEUP.

Sensores dinámicos

Los sensores dinámicos se mostraban con la función poll() en la HAL de sensores 1.0. La HAL de sensores AIDL requiere que se llame a onDynamicSensorsConnected y onDynamicSensorsDisconnected en ISensorsCallback cada vez que cambien las conexiones de sensores dinámicos. Estas devoluciones de llamada están disponibles como parte del puntero ISensorsCallback que se proporciona a través de la función initialize().

Modos de operación

Se debe admitir el modo DATA_INJECTION para los sensores WAKE_UP.

Compatibilidad con Multi-HAL

La HAL de sensores AIDL admite Multi-HAL con el framework de Multi-HAL de sensores. Para obtener detalles de la implementación, consulta Cómo realizar la portabilidad desde la HAL de sensores 2.1.