Sensores Multi-HAL

El Multi-HAL de sensores es un framework que permite que los HAL de sensores se ejecuten junto con otros HAL de sensores. El Multi-HAL de sensores carga de forma dinámica los sub-HAL de sensores almacenados 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 liberación del bloqueo de activación. Una sub-HAL de sensores es una HAL de sensores integrada en un objeto compartido en la partición del proveedor y que utiliza el framework de Multi-HAL. Estos sub-HALs no dependen entre sí ni del código multi-HAL que contiene la función principal del 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 sub-HAL deben usar las APIs de sub-HAL definidas en el encabezado SubHal 2.1.

En los dispositivos que ejecutan Android 13 o versiones posteriores y que usan la HAL del AIDL de sensores, puedes usar la capa de shim de Multi-HAL para permitir la capacidad de Multi-HAL. Para obtener detalles de la implementación, consulta Cómo usar la HAL de sensores Multi-HAL con la HAL de sensores AIDL.

Diferencia entre Sensors Multi-HAL 2 y Sensors HAL 2

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

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

  • El método initialize pasa una clase IHalProxyCallback en lugar de dos FMQ y ISensorsCallback.
  • Los sub-HAL deben implementar una función de depuración para proporcionar información de depuración en los informes de errores.
  • Los sub-HAL deben implementar una función de nombre para que el sub-HAL cargado se pueda distinguir de otros sub-HAL.

La principal diferencia entre Sensors Multi-HAL 2 y Sensors 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. En segundo plano, la Multi-HAL de sensores administra todas las interacciones con las FMQ para garantizar la entrega oportuna de eventos de sensores para todas las sub-HAL. Se recomienda que los sub-HALs usen el método createScopedWakelock para delegar la carga de los tiempos de espera de los bloqueos de activación en el Multi-HAL de Sensors y centralizar el uso de los bloqueos de activación en un bloqueo de activación común para todo el Multi-HAL de Sensors, lo que minimiza las llamadas de bloqueo y desbloqueo.

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

Código fuente y referencia de implementación

Todo el código de Multi-HAL de sensores está disponible en hardware/interfaces/sensors/common/default/2.X/multihal/. Estos son algunos recursos que pueden ayudarte.

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

    Para las 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/: Esta implementación secundaria del HAL de ejemplo usa sensores simulados para generar datos simulados. Es útil para probar cómo interactúan varios sub-HAL en un dispositivo.

Implementación

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

Cómo usar la HAL de sensores Multi-HAL con la HAL de sensores AIDL

Para permitir la capacidad de Multi-HAL con la HAL del AIDL de Sensors, importa el módulo de la capa de adaptación de Multi-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 sensores de AIDL y HIDL, y define un wrapper alrededor de la interfaz de Multi-HAL que se describe en Implementación de Multi-HAL de sensores 2.1. La capa de simulación de Multi-HAL de AIDL es compatible con los dispositivos que implementan la versión 2.1 de Multi-HAL de sensores.

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

Implementa los sensores Multi-HAL 2.1

Para implementar Sensors 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 destino cc_library_shared para compilar el sub-HAL recién implementado. Cuando agregues el destino, 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.

    Para ver un ejemplo de entrada de Android.bp para compilar una biblioteca de sub-HAL, consulta hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

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

  5. Quita todos los archivos de servicio android.hardware.sensors y 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, se busca el sub-HAL recién implementado y se inicializa llamando a sensorsHalGetSubHal_2_1.

Portabilidad de 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 tu sub-HAL.

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

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

Portabilidad desde la HAL de sensores 2.0

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

Inicializa el HAL

La HAL de sensores 2.0 tiene una función de inicialización que permite que el servicio de sensores pase FMQ y una devolución de llamada de sensor dinámico. 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 las conexiones y desconexiones de sensores dinámicos.

Publica eventos de sensores en la implementación de Multi-HAL

En lugar de publicar eventos del sensor a través de la FMQ, el sub-HAL debe escribir eventos del sensor en IHalProxyCallback cuando haya eventos del sensor 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 Sensors Multi-HAL 2.0, los sub-HAL permiten que la implementación de Multi-HAL administre los bloqueos de activación y puede solicitar que se adquiera un bloqueo de activación invocando createScopedWakelock. Se debe adquirir un bloqueo de activación con alcance bloqueado y pasarlo a postEvents cuando se publiquen eventos de activación en la implementación de Multi-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 de los sensores. Estas devoluciones de llamada están disponibles como parte del puntero IHalProxyCallback que se proporciona a través de la función initialize().

Portabilidad desde la HAL de sensores 1.0

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

Inicializa el HAL

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

Expone los sensores disponibles

En Sensors Multi-HAL 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. 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.

Publica eventos de sensores 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 forma proactiva eventos de sensores en IHalProxyCallback cada vez que haya eventos de sensores 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 Sensors Multi-HAL 2.0, los sub-HAL permiten que la implementación de Multi-HAL administre los bloqueos de activación y puede solicitar que se adquiera un bloqueo de activación invocando createScopedWakelock. Se debe adquirir un bloqueo de activación con alcance bloqueado y pasarlo a postEvents cuando se publiquen eventos de activación en la implementación de Multi-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 de los sensores. Estas devoluciones de llamada están disponibles como parte del puntero IHalProxyCallback que se proporciona a través de la función initialize().

Portabilidad desde Sensors Multi-HAL 1.0

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

  1. Asegúrate de que la configuración del HAL de los sensores se encuentre 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. Transfiere sub-HALs como se describe en Transferencia de la HAL de sensores 1.0.
  4. Establece Sensors Multi-HAL 2.0 como la HAL designada siguiendo los pasos 3 y 4 de la sección Implementación de Sensors Multi-HAL 2.0.

Validación

Ejecuta VTS

Cuando hayas integrado uno o más sub-HAL con Sensors Multi-HAL 2.1, usa el Vendor Test Suite (VTS) para asegurarte de que tus implementaciones de sub-HAL cumplan con todos los requisitos establecidos por la interfaz de la HAL de sensores.

Para ejecutar solo las pruebas de VTS de sensores cuando VTS está configurado en una máquina host, 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 ejecutas la capa de simulación de Multi-HAL de AIDL, ejecuta VtsAidlHalSensorsTargetTest.

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

Ejecuta pruebas de unidades

Las pruebas de unidades en HalProxy_test.cpp prueban HalProxy con sub-HAL simulados que se crean en la prueba de unidades y no se cargan de forma dinámica. Cuando crees un sub-HAL nuevo, estas pruebas deberían servir como guía para agregar pruebas de unidades que verifiquen que el nuevo sub-HAL se implementó 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 los sub-HAL simulados

Los sub-HAL simulados son implementaciones ficticias de la interfaz ISensorsSubHal. Los sub-HAL exponen diferentes listas de sensores. Cuando se activan los sensores, publican periódicamente eventos de sensores generados automáticamente en HalProxy según los intervalos especificados en una solicitud de sensor determinada.

Los sub-HAL simulados se pueden usar para probar cómo funciona el código completo de Multi-HAL con otros sub-HAL cargados en el sistema y para probar varios aspectos del código de Multi-HAL de Sensors.

Hay dos sub-HAL falsos disponibles en hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

Para compilar y enviar los sub-HAL simulados a un dispositivo, sigue estos pasos:

  1. Ejecuta los siguientes comandos para compilar y enviar los tres sub-HAL simulados 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 del HAL de sensores en /vendor/etc/sensors/hals.conf con las rutas de acceso de los sub-HAL simulados.

    /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 los nuevos sub-HAL 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 del HAL de Sensors, ejecuta el siguiente comando:

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

Luego, se envía información sobre el estado actual de HalProxy y sus sub-HAL a la terminal. A continuación, se muestra un ejemplo del resultado del comando para el objeto HalProxy y las sub-HAL simuladas.

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 un número grande (1,000 o más), esto indica que hay muchos eventos pendientes de escribirse en el framework de sensores. Esto indica que el servicio de sensores está en un punto muerto o falló, y no procesa eventos de sensores, o que recientemente se publicó un lote grande de eventos de sensores desde un sub-HAL.

Si el recuento de referencias de bloqueo de activación es mayor que 0, significa que HalProxy adquirió un bloqueo de activación. Solo debe ser mayor que 0 si se mantiene intencionalmente un ScopedWakelock o si se enviaron eventos de activación a HalProxy y el framework del sensor no los procesó.

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