Sensores HAL 2.0

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

La HAL de Sensors 2.0 está disponible en Android 10 y versiones posteriores para dispositivos nuevos y actualizados. El HAL de sensores 2.0 se basa en el HAL de sensores 1.0, pero tiene varias diferencias clave que impiden que sea compatible con versiones anteriores. La HAL de sensores 2.0 usa colas de mensajes rápidos (FMQ) para enviar eventos de sensores desde la HAL al framework de sensores de Android.

La HAL de Sensors 2.1 está disponible en Android 11 y versiones posteriores para dispositivos nuevos y actualizados. La HAL de sensores 2.1 es una iteración de la HAL de sensores 2.0 que expone el tipo de sensor HINGE_ANGLE y actualiza varios métodos para aceptar el tipo HINGE_ANGLE.

Interfaz de HAL 2.1

La principal fuente de documentación para la HAL de Sensors 2.1 se encuentra dentro de la definición de la HAL en hardware/interfaces/sensors/2.1/ISensors.hal. Si hay un conflicto de requisitos entre esta página y ISensors.hal, usa el requisito de ISensors.hal.

Interfaz de HAL 2.0

La principal fuente de documentación para la HAL de sensores 2.0 se encuentra dentro de la definición de la HAL en hardware/interfaces/sensors/2.0/ISensors.hal. Si hay un conflicto de requisitos entre esta página y ISensors.hal, usa el requisito de ISensors.hal.

Implementa la HAL de sensores 2.0 y la HAL 2.1

Para implementar la HAL de sensores 2.0 o 2.1, un objeto debe extender la interfaz ISensors y, luego, implementar todas las funciones definidas en 2.0/ISensors.hal o 2.1/ISensors.hal.

Inicializa el 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 la HAL 2.0 y a la función initialize_2_1() para la HAL 2.1 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 la FMQ de eventos que se usa para escribir eventos de sensores en el framework. El HAL usa el segundo descriptor para crear el FMQ de bloqueo de activación que se usa para sincronizar cuando el HAL libera su bloqueo de activación para los eventos del sensor WAKE_UP. El 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() o initialize_2_1() debe ser la primera función a la que se llama cuando se inicializa el HAL de Sensors.

Expone los sensores disponibles

Para obtener una lista de todos los sensores estáticos disponibles en el dispositivo, usa la función getSensorsList() en HAL 2.0 y la función getSensorsList_2_1() en HAL 2.1. Esta función devuelve una lista de sensores, cada uno identificado de forma única por su identificador. El identificador de un sensor determinado no debe cambiar cuando se reinicia el proceso que aloja la HAL de Sensors. Los identificadores pueden cambiar cuando se reinicia el dispositivo y cuando se reinicia el 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 devuelve a las apps que utilizan la función getDefaultSensor(int sensorType, bool wakeUp).

Estabilidad de la lista de sensores

Después de reiniciar el HAL de sensores, si los datos que devuelven getSensorsList() o getSensorsList_2_1() 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 los casos en los que falta un sensor con un identificador determinado o este tiene atributos modificados, o bien cuando se introducen sensores nuevos. Si bien 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 establece 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 cambios innecesarios en la lista de sensores.

Para garantizar identificadores de sensores estables, la HAL debe asignar de forma determinística un sensor físico determinado en el dispositivo a su identificador. Si bien la interfaz HAL de Sensors no exige una 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 el HAL debe saber cuándo todos los sensores esperados completaron la inicialización antes de regresar de getSensorsList() o getSensorsList_2_1(). Esta lista de sensores esperados se puede compilar en el archivo binario del HAL o almacenar en un archivo de configuración en el sistema de archivos, y el orden de aparición se puede usar para derivar identificadores estables. Si bien la mejor solución depende de los detalles específicos de la implementación de tu HAL, el requisito clave es que los identificadores de sensores no cambien cuando se reinicie el HAL.

Cómo configurar los sensores

Antes de que se active un sensor, se debe configurar con un período de muestreo y una latencia de informes máxima con 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 configure:

  • Continuo: Los eventos del sensor se generan a una velocidad continua.
  • En el cambio: Los eventos se generan con una frecuencia no mayor que el período de muestreo y pueden generarse a una frecuencia menor que el período de muestreo si el valor medido no cambia.
  • Única: 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 los eventos pueden retrasarse y almacenarse en la FIFO de hardware antes de escribirse en la FMQ de eventos a través de la HAL mientras el SoC está activo.

Un valor de cero significa que los eventos se deben informar tan pronto como se midan, ya sea omitiendo la FIFO por completo o vaciándola tan pronto como haya un evento del sensor en la 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 del sensor tan pronto como se detectan. Los eventos se pueden almacenar temporalmente en la FIFO de hardware y se pueden informar en lotes, siempre y cuando 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 de inmediato. Esto reduce la cantidad de interrupciones enviadas al SoC y permite que este cambie a un modo de menor consumo mientras el sensor captura y agrupa datos.

Cada evento tiene una marca de tiempo asociada. El retraso en el momento en que se registra 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 más información y conocer los requisitos para informar eventos del sensor con una latencia de informes máxima distinta de cero, consulta Procesamiento por lotes.

Cómo activar 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 que se desactiva un sensor, no se deben escribir eventos adicionales de ese sensor en la FMQ de eventos.

Sensores de descarga

Si un sensor está configurado para procesar datos de sensores por lotes, el framework puede forzar una descarga inmediata de los eventos de sensores por lotes llamando a flush(). Esto hace que los eventos del sensor por lotes para el identificador de sensor especificado se escriban de inmediato en la FMQ de eventos. El HAL de Sensors debe agregar un evento de descarga completa al final de los eventos del sensor que se escriben como resultado de una llamada a flush().

La limpieza ocurre de forma asíncrona (es decir, esta función debe devolver un valor de inmediato). Si la implementación usa una sola FIFO para varios sensores, se vacía esa FIFO y se agrega el evento de vaciado completo solo para el sensor especificado.

Si el sensor especificado no tiene FIFO (no se puede almacenar 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 descarga completa para ese sensor. Esto se aplica a todos los sensores, excepto a los de un solo disparo.

Si se llama a flush() para un sensor de un solo disparo, flush() debe devolver BAD_VALUE y no generar un evento de descarga completa.

Escribe eventos del sensor en la FMQ

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

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

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

Las HAL de sensores 2.0 y 2.1 admiten write y writeBlocking en la 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 el framework establece cuando lee eventos de la FMQ de eventos. La marca de notificación de escritura debe establecerse en EventQueueFlagBits::READ_AND_PROCESS, lo que notifica al framework que se escribieron eventos en la FMQ de eventos.

Eventos WAKE_UP

Los eventos WAKE_UP son eventos del sensor 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 la FMQ de eventos, el 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 el HAL de Sensors libere su bloqueo de activación. Para sincronizarte cuando el HAL de Sensors libera su bloqueo de activación, usa la FMQ de Wake Lock.

El HAL de Sensors debe leer la FMQ de Wake Lock para determinar la cantidad de eventos WAKE_UP que controló el framework. El 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 del sensor, el framework cuenta la cantidad de eventos marcados como eventos WAKE_UP y vuelve a escribir este número en la FMQ de bloqueo de activación.

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

Sensores dinámicos

Los sensores dinámicos son aquellos que no forman parte física del dispositivo, pero se pueden usar como entrada para él, 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 el HAL de Sensors. 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 del sensor se escriben en una memoria específica en lugar de en la FMQ de eventos, lo que omite el marco de trabajo de sensores de Android. Un cliente que registra un canal directo debe leer los eventos del sensor directamente desde la memoria que se usó para crear el canal directo y no recibirá los eventos del sensor 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 canal directo nuevo.

Modos de operación

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

Por lo general, la función injectSensorData() en la HAL 2.0 y la función injectSensorsData_2_1() en la HAL 2.0 se usan 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 del HAL de Sensors, ejecuta las pruebas de CTS y VTS de sensores.

Pruebas de CTS

Las pruebas de CTS de sensores existen tanto en las pruebas de CTS automatizadas como en la app manual de CTS Verifier.

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, el procesamiento por lotes 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 del 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 2.0 se encuentran en hardware/interfaces/sensors/2.0/vts. Las pruebas de VTS para la HAL de Sensors 2.1 se encuentran en hardware/interfaces/sensors/2.1/vts. Estas pruebas garantizan que el HAL de Sensors se implemente correctamente y que se cumplan todos los requisitos dentro de ISensors.hal y ISensorsCallback.hal.

Actualización de la HAL de sensores 2.0 a la 2.1

Cuando actualices a la HAL de sensores 2.1 desde la 2.0, tu implementación de la HAL debe incluir los métodos initialize_2_1(), getSensorsList_2_1() y injectSensorsData_2_1(), junto con los tipos de la HAL 2.1. Estos métodos deben cumplir con los mismos requisitos que se describieron para la HAL 2.0 más arriba.

Dado que las HAL de versiones secundarias deben admitir todas las funciones de las HAL anteriores, las HAL de 2.1 deben admitir la inicialización como HAL de 2.0. Para evitar la complejidad de admitir ambas versiones del HAL, se recomienda usar Multi-HAL 2.1.

Para ver un ejemplo de cómo implementar tu propio HAL de Sensors 2.1, consulta Sensors.h.

Actualiza a la HAL de sensores 2.0 desde la versión 1.0

Cuando actualices la HAL de sensores 1.0 a la versión 2.0, asegúrate de que tu implementación de la HAL cumpla con los siguientes requisitos.

Inicializa el HAL

La función initialize() debe ser compatible para establecer FMQ entre el framework y el HAL.

Expone los sensores disponibles

En la HAL de sensores 2.0, la función getSensorsList() debe devolver 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 devolver el mismo valor durante un solo inicio del dispositivo, incluso en los reinicios del HAL de Sensors. Esto permite que el framework intente restablecer las conexiones del sensor si se reinicia el servidor del sistema. El valor que devuelve getSensorsList() puede cambiar después de que el dispositivo se reinicie.

Escribe eventos del sensor en la FMQ

En lugar de esperar a que se llame a poll(), en la HAL de sensores 2.0, la HAL de sensores debe escribir de forma proactiva eventos de sensores en la FMQ de eventos siempre que haya eventos de sensores disponibles. El 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 el HAL de sensores 1.0, el 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 del sensor y había obtenido un bloqueo de activación, si era necesario. Debido a que, en la HAL de sensores 2.0, la HAL ya no sabe cuándo el framework procesó los eventos escritos en la FMQ, la FMQ de bloqueo de activación permite que el framework se comunique con la HAL cuando controló los eventos de WAKE_UP.

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

Sensores dinámicos

Los sensores dinámicos se devolvían con la función poll() en la HAL de sensores 1.0. El HAL de sensores 2.0 requiere que se llamen a onDynamicSensorsConnected y onDynamicSensorsDisconnected en ISensorsCallback cada vez que cambien las conexiones dinámicas de los sensores. 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

El modo DATA_INJECTION para los sensores WAKE_UP debe ser compatible con la HAL de sensores 2.0.

Compatibilidad con múltiples HAL

Las HAL de sensores 2.0 y 2.1 admiten Multi-HAL con el framework de Multi-HAL de sensores. Para obtener detalles de la implementación, consulta Cómo portar desde la HAL de sensores 1.0.