Multi-HAL de sensores

La multi-HAL de sensores es un framework que permite que las HAL de sensores se ejecuten junto con otras HAL de sensores. La multi-HAL de sensores carga de forma dinámica las subHAL de sensores almacenadas como bibliotecas dinámicas en la partición del proveedor y les proporciona un objeto de devolución de llamada que puede controlar la publicación de eventos y la adquisición y la liberación del bloqueo de activación. Una subHAL de sensores es una HAL de sensores integrada en un objeto compartido en la partición del proveedor que usa el framework de varias HAL. Estas subHAL no dependen unos de otros ni del código de varias HAL que contiene la función principal para el proceso.

Los sensores Multi-HAL 2.1, disponibles en dispositivos que ejecutan Android 11 o versiones posteriores, son una iteración de los sensores Multi-HAL 2.0 que admite la carga de sub-HAL que pueden exponer el tipo de sensor de ángulo de bisagra. Para admitir este tipo de sensor, los subHAL deben usar las APIs de subHAL definidas en el encabezado SubHal 2.1.

En el caso de los dispositivos que ejecutan Android 13 o versiones posteriores que usan la HAL del AIDL de sensores, puedes usar la capa de corrección de compatibilidad de varias HAL para permitir la función de varias HAL. Para obtener detalles sobre la implementación, consulta Cómo usar la HAL de varios sensores con la HAL del AIDL de sensores.

Diferencia entre sensores Multi-HAL 2 y Sensores HAL 2

Los sensores Multi-HAL 2, disponibles en dispositivos que ejecutan Android 10 o versiones posteriores, introducen varias abstracciones además de la HAL de sensores 2 para facilitar la interacción con las APIs de HAL. Multi-HAL 2 de sensores introduce la clase HalProxy para controlar la implementación de la interfaz de la HAL de sensores 2 y la interfaz de V2_1/SubHal (o V2_0/SubHal) para permitir que HalProxy interactúe con subHAL.

La interfaz ISensorsSubHal se diferencia de la interfaz 2.1/ISensors.hal (o 2.0/ISensors.hal) de las siguientes maneras:

  • El método de inicialización pasa una clase IHalProxyCallback en lugar de dos FMQ y ISensorsCallback.
  • Las subHAL deben implementar una función de depuración para proporcionar información de depuración en los informes de errores.
  • Las subHAL deben implementar una función de nombre para que la subHAL cargada pueda distinguirse de otras subHAL.

La principal diferencia entre los sensores Multi-HAL 2 y los sensores HAL 2 se encuentra en las funciones de inicialización. En lugar de proporcionar FMQ, la interfaz IHalProxyCallback proporciona dos métodos: uno para publicar eventos de sensores en el framework de sensores y otro para crear bloqueos de activación. De forma interna, la HAL de sensores múltiples administra todas las interacciones con las FMQ para garantizar la entrega oportuna de eventos de sensores para todas las subHAL. Se recomienda que las subHAL usen el método createScopedWakelock para delegar la carga de agotar el tiempo de espera de los bloqueos de activación a la HAL de sensores múltiples y centralizar el uso de bloqueo de activación en un bloqueo de activación común para toda la HAL de sensores, lo que minimiza las llamadas de bloqueo y desbloqueo.

Los sensores Multi-HAL 2 también tienen algunas funciones de seguridad integradas. Controla situaciones en las que el FMQ del sensor está lleno o en las que el framework del sensor de Android se reinicia y el estado del sensor debe restablecerse. Además, cuando los eventos se publican en la clase HalProxy, pero el framework del sensor no puede aceptarlos de inmediato, la Multi-HAL de sensores puede mover los eventos a un subproceso en segundo plano para permitir que el trabajo continúe en todas las subHAL mientras espera que se publiquen los eventos.

Implementación del código fuente y la referencia

Todo el código de HAL de sensores está disponible en hardware/interfaces/sensors/common/default/2.X/multihal/. A continuación, se incluyen algunas indicaciones para algunos recursos.

  • HalProxy.h: La multi-HAL de los sensores crea instancias del objeto HalProxy y controla el paso de datos de las subHAL al framework del sensor.
  • HalProxy.cpp: La implementación de HalProxy contiene toda la lógica necesaria para multiplexar la comunicación entre subHAL y el framework del sensor.
  • SubHal.h: La interfaz ISensorsSubHal define la interfaz que deben seguir las subHAL para ser compatibles con HalProxy. La subHAL implementa el método de inicialización de modo que se pueda usar el objeto HalProxyCallback para postEvents y createScopedWakelock.

    Para implementaciones de Multi-HAL 2.0, usa la versión 2.0 de SubHal.h.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: Estas pruebas de unidades verifican la implementación de HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: En esta implementación de subHAL de ejemplo, se usan sensores falsos para generar datos falsos. Es útil para probar cómo interactúan varias subHAL en un dispositivo.

Implementación

En esta sección, se describe cómo implementar sensores Multi-HAL en las siguientes situaciones:

Cómo usar la HAL de sensores múltiples con la HAL de sensores AIDL

Para permitir la capacidad de varias HAL con la HAL del AIDL de sensores, importa el módulo de la capa de corrección de compatibilidad de varias HAL del AIDL, que se encuentra en hardware/interfaces/sensors/aidl/default/multihal/. El módulo controla la conversión entre los tipos de definición de HAL de los sensores AIDL y HIDL, y define un wrapper alrededor de la interfaz de varias HAL descrita en Cómo implementar sensores Multi-HAL 2.1. La capa de corrección de compatibilidad de varias HAL del AIDL es compatible con dispositivos que implementan sensores Multi-HAL 2.1.

La capa de corrección de compatibilidad de varias HAL del AIDL te permite exponer el rastreador de la cabeza y los tipos de sensores IMU de eje limitado en la HAL del AIDL de sensores. Para usar estos tipos de sensores definidos por la interfaz de la HAL del AIDL, configura el campo type en la estructura SensorInfo en la implementación de getSensorsList_2_1(). Esto es seguro, ya que los campos de tipo de sensor respaldados por números enteros de la HAL de los sensores HIDL y AIDL no se superponen.

Cómo implementar sensores Multi-HAL 2.1

Para implementar sensores Multi-HAL 2.1 en un dispositivo nuevo, sigue estos pasos:

  1. Implementa la interfaz ISensorsSubHal como se describe en SubHal.h.
  2. Implementa el método sensorsHalGetSubHal_2_1 en SubHal.h.
  3. Agrega un objetivo cc_library_shared para compilar la subHAL recién implementada. Cuando agregues el objetivo, ten en cuenta lo siguiente:

    1. Asegúrate de que el destino se envíe a algún lugar de la partición del proveedor del dispositivo.
    2. En el archivo de configuración ubicado en /vendor/etc/sensors/hals.conf, agrega la ruta de acceso a la biblioteca en una línea nueva. Si es necesario, crea el archivo hals.conf.

    Si quieres ver una entrada Android.bp de ejemplo para compilar una biblioteca de subHAL, consulta hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Quita todas las entradas android.hardware.sensors del archivo manifest.xml, que contiene la lista de HALs compatibles con el dispositivo.

  5. Quita todos los servicios android.hardware.sensors y los archivos service.rc del archivo device.mk, y agrega android.hardware.sensors@2.1-service.multihal y android.hardware.sensors@2.1-service.multihal.rc a PRODUCT_PACKAGES.

Durante el inicio, se inicia HalProxy, busca la subHAL recién implementada y la inicializa llamando a sensorsHalGetSubHal_2_1.

Puerto de sensores Multi-HAL 2.0 a Multi-HAL 2.1

Para realizar la portabilidad de Multi-HAL 2.0 a Multi-HAL 2.1, implementa la interfaz SubHal y vuelve a compilar la subHAL.

Estas son las diferencias entre las interfaces SubHal 2.0 y 2.1:

  • IHalProxyCallback usa los tipos creados en la versión 2.1 de la especificación ISensors.hal.
  • La función initialize() pasa un IHalProxyCallback nuevo en lugar del de la interfaz SubHal 2.0.
  • Las subHAL deben implementar getSensorsList_2_1 y injectSensorData_2_1 en lugar de getSensorsList y injectSensorData, ya que estos métodos usan los nuevos tipos que se agregaron en la versión 2.1 de la especificación ISensors.hal.
  • Las subHAL deben exponer sensorsHalGetSubHal_2_1 en lugar de sensorsHalGetSubHal para que la multiHAL las trate como subHAL de la versión 2.1.

Puerto del HAL de sensores 2.0

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

Cómo inicializar la HAL

La HAL de sensores 2.0 tiene una función de inicialización que permite que el servicio de sensores pase las FMQ y una devolución de llamada dinámica del sensor. En Sensors Multi-HAL 2.0, la función initialize() pasa una sola devolución de llamada que se debe usar para publicar eventos de sensores, obtener bloqueos de activación y notificar la conexión y desconexión de sensores dinámicos.

Publicación de eventos del sensor en la implementación de Multi-HAL

En lugar de publicar eventos del sensor a través de FMQ, la subHAL debe escribir los eventos del sensor en el IHalProxyCallback cuando los eventos del sensor están disponibles.

Eventos WAKE_UP

En la HAL de sensores 2.0, la HAL puede administrar el bloqueo de activación para su implementación. En el caso de Multi-HAL de sensores 2.0, las subHAL permiten que la implementación de varias HAL administre los bloqueos de activación y pueden solicitar que se adquiera uno mediante la invocación de createScopedWakelock. Se debe adquirir un bloqueo de activación con alcance bloqueado y pasarlo a postEvents cuando se publican eventos de activación en la implementación de varias HAL.

Sensores dinámicos

Los sensores Multi-HAL 2.0 requieren que se llame a onDynamicSensorsConnected y onDynamicSensorsDisconnected en IHalProxyCallback cada vez que cambien las conexiones dinámicas del sensor. Estas devoluciones de llamada están disponibles como parte del puntero IHalProxyCallback que se proporciona a través de la función initialize().

Puerto del HAL de sensores 1.0

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

Cómo inicializar la HAL

Se debe admitir la función initialize() para establecer la devolución de llamada entre la subHAL y la implementación de varias HAL.

Cómo exponer los sensores disponibles

En Sensors Multi-HAL 2.0, la función getSensorsList() debe mostrar el mismo valor durante el inicio de un solo dispositivo, incluso entre los reinicios de la HAL de los sensores. Esto permite que el framework intente restablecer las conexiones de los sensores si se reinicia el servidor del sistema. El valor que muestra getSensorsList() puede cambiar después de que el dispositivo realiza un reinicio.

Publicación de eventos del sensor en la implementación de Multi-HAL

En la HAL de sensores 2.0, en lugar de esperar a que se llame a poll(), la sub-HAL debe escribir de manera proactiva los eventos de sensores en IHalProxyCallback siempre que estén disponibles.

Eventos WAKE_UP

En la HAL de sensores 1.0, la HAL puede administrar el bloqueo de activación para su implementación. En el caso de Multi-HAL de sensores 2.0, las subHAL permiten que la implementación de varias HAL administre los bloqueos de activación y pueden solicitar que se adquiera uno mediante la invocación de createScopedWakelock. Se debe adquirir un bloqueo de activación con alcance bloqueado y pasarlo a postEvents cuando se publican eventos de activación en la implementación de varias HAL.

Sensores dinámicos

En la HAL de sensores 1.0, los sensores dinámicos se devuelven a través de la función poll(). Los sensores Multi-HAL 2.0 requieren que se llame a onDynamicSensorsConnected y onDynamicSensorsDisconnected en IHalProxyCallback cada vez que cambien las conexiones dinámicas del sensor. Estas devoluciones de llamada están disponibles como parte del puntero IHalProxyCallback que se proporciona a través de la función initialize().

Puerto de los sensores Multi-HAL 1.0

Para transferir una implementación existente de Sensores Multi-HAL 1.0, sigue estos pasos.

  1. Asegúrate de que la configuración de la HAL de los sensores esté ubicada en /vendor/etc/sensors/hals.conf. Esto podría implicar mover el archivo ubicado en /system/etc/sensors/hals.conf.
  2. Quita cualquier referencia a hardware/hardware.h y hardware/sensors.h, ya que no son compatibles con HAL 2.0.
  3. Conectar las subHAL como se describe en Portabilidad desde los sensores Hal 1.0.
  4. Establece sensores Multi-HAL 2.0 como la HAL designada siguiendo los pasos 3 y 4 en la sección Cómo implementar sensores múltiples-HAL 2.0.

Validación

Ejecuta VTS

Cuando integres una o más subHAL con sensores Multi-Hal 2.1, usa el Conjunto de pruebas de proveedores (VTS) para asegurarte de que las implementaciones de tu subHAL cumplan con todos los requisitos que establece la interfaz de la HAL de sensores.

Para ejecutar solo las pruebas de VTS de los sensores cuando el VTS está configurado en una máquina anfitrión, ejecuta los siguientes comandos:

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

Si estás ejecutando la capa de corrección de compatibilidad de varias HAL del AIDL, ejecuta VtsAidlHalSensorsTargetTest.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

Cómo ejecutar pruebas de unidades

Las pruebas de unidades en HalProxy_test.cpp prueban HalProxy con subHAL falsas de las que se crean instancias en la prueba de unidades y que no se cargan de forma dinámica. Cuando se crea una nueva subHAL, estas pruebas deben servir como guía para agregar pruebas de unidades que verifiquen que la nueva subHAL se implemente correctamente.

Para ejecutar las pruebas, ejecuta los siguientes comandos:

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

Cómo realizar pruebas con las subHAL falsas

Las subHAL falsas son implementaciones ficticias de la interfaz ISensorsSubHal. Las subHAL exponen diferentes listas de sensores. Cuando se activan los sensores, publican periódicamente eventos de sensores generados automáticamente en HalProxy en función de los intervalos especificados en una solicitud de sensor determinada.

Se pueden usar las subHAL falsas para probar cómo funciona el código completo de varias HAL con otras subHAL cargadas en el sistema y para destacar varios aspectos del código de la multi-HAL de sensores.

Hay dos subHAL falsas disponibles en hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

Para compilar y enviar las subHAL falsas a un dispositivo, sigue estos pasos:

  1. Ejecuta los siguientes comandos para compilar y enviar las tres subHAL falsas diferentes al dispositivo:

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  2. Actualiza la configuración de la HAL de sensores en /vendor/etc/sensors/hals.conf con las rutas de acceso de las subHAL falsas.

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. Reinicia HalProxy y carga las nuevas subHAL que se indican en la configuración.

    adb shell stop
    adb shell start
    

Depuración

Los desarrolladores pueden depurar el framework con el comando lshal. Para solicitar el resultado de depuración de la HAL de sensores, ejecuta el siguiente comando:

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

La información sobre el estado actual de HalProxy y sus subHAL se envía a la terminal. A continuación, se muestra un ejemplo del resultado del comando para el objeto HalProxy y las subHAL falsas.

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

Si el número especificado para # of events on pending write queue es grande (1,000 o más), esto indica que hay muchos eventos pendientes para escribir en el framework de los sensores. Esto indica que el servicio de sensores está interbloqueado o se produjo una falla y no está procesando eventos del sensor, o que un gran lote de eventos de sensores se publicó recientemente desde una subHAL.

Si el recuento de referencias de bloqueo de activación es mayor que 0, significa que HalProxy adquirió un bloqueo de activación. El valor solo debería ser mayor que 0 si se retiene intencionalmente un ScopedWakelock o si se enviaron eventos de activación a HalProxy y el framework del sensor no los procesó.

El descriptor de archivos que se pasa al método de depuración de HalProxy se pasa a cada sub-HAL, de modo que los desarrolladores deben implementar el método de depuración como parte de la interfaz ISensorsSubHal.