Implementar Health 2.1

En Android 11, todo el código healthd se refactoriza en libhealthloop y libhealth2impl y, luego, se modifica para implementar la HAL health@2.1. Estas dos bibliotecas están vinculadas estáticamente por health@2.0-impl-2.1, la implementación de transferencia de Health 2.1. Las bibliotecas vinculadas de forma estática permiten que health@2.0-impl-2.1 realice el mismo trabajo que healthd, como ejecutar healthd_mainloop y sondear. En init, health@2.1-service registra una implementación de la interfaz IHealth en hwservicemanager. Cuando se actualizan dispositivos con una imagen del proveedor de Android 8.x o 9 y un framework de Android 11, es posible que la imagen del proveedor no proporcione el servicio de health@2.1. La programación de baja aplica la compatibilidad con versiones anteriores de las imágenes de proveedores anteriores.

Para garantizar la retrocompatibilidad, haz lo siguiente:

  1. healthd registra IHealth en hwservicemanager a pesar de ser un daemon del sistema. Se agrega IHealth al manifiesto del sistema, con el nombre de la instancia "backup".
  2. El framework y storaged se comunican con healthd a través de hwbinder en lugar de binder.
  3. El código del framework y storaged se cambia para recuperar la instancia "predeterminada" si está disponible y, luego, "copia de seguridad".
    • El código del cliente C++ usa la lógica definida en libhealthhalutils.
    • El código de cliente de Java usa la lógica definida en HealthServiceWrapper.
  4. Una vez que IHealth/default esté disponible de forma general y las imágenes del proveedor de Android 8.1 dejen de estar disponibles, IHealth/backup y healthd pueden dejar de estar disponibles. Para obtener más detalles, consulta health@1.0 dejó de estar disponible.

Variables de compilación específicas de la placa para Healthd

BOARD_PERIODIC_CHORES_INTERVAL_* son variables específicas de la placa que se usan para compilar healthd. Como parte de la división de compilación del sistema o del proveedor, no se pueden definir valores específicos de la placa para los módulos del sistema. Estos valores solían anularse en la función obsoleta healthd_board_init.

En health@2.1, los proveedores pueden anular estos dos valores de intervalo de tareas periódicas en la estructura healthd_config antes de pasarlos al constructor de la clase de implementación de estado. La clase de implementación de estado debe heredar de android::hardware::health::V2_1::implementation::Health.

Implementa el servicio de Health 2.1

Para obtener información sobre la implementación del servicio Health 2.1, consulta hardware/interfaces/health/2.1/README.md.

Clientes de Health

health@2.x tiene los siguientes clientes:

  • cargador. El uso del código libbatterymonitor y healthd_common se une en health@2.0-impl.
  • recuperación. La vinculación a libbatterymonitor se une a health@2.0-impl. Todas las llamadas a BatteryMonitor se reemplazan por llamadas a la clase de implementación de Health.
  • BatteryManager. BatteryManager.queryProperty(int id) era el único cliente de IBatteryPropertiesRegistrar.getProperty. healthd proporcionó IBatteryPropertiesRegistrar.getProperty y leyó directamente /sys/class/power_supply.

    Como medida de seguridad, las apps no pueden llamar al HAL de salud directamente. En Android 9 y versiones posteriores, BatteryService proporciona el servicio de Binder IBatteryPropertiesRegistrar, en lugar de healthd. BatteryService delega la llamada a la HAL de estado para recuperar la información solicitada.

  • BatteryService. En Android 9 y versiones posteriores, BatteryService usa HealthServiceWrapper para determinar si se debe usar la instancia del servicio de salud predeterminada de vendor o la instancia del servicio de salud de respaldo de healthd. Luego, BatteryService escucha los eventos de salud a través de IHealth.registerCallback.

  • Almacenado. En Android 9 y versiones posteriores, storaged usa libhealthhalutils para determinar si se debe usar la instancia del servicio de salud predeterminada de vendor o la instancia del servicio de salud de respaldo de healthd. Luego, storaged escucha eventos de salud a través de IHealth.registerCallback y recupera información de almacenamiento.

Cambios de SELinux

El HAL de health@2.1 incluye los siguientes cambios de SELinux en la plataforma:

  • Se agregó android.hardware.health@2.1-service a file_contexts.

En el caso de los dispositivos con su propia implementación, es posible que se deban realizar algunos cambios en SELinux del proveedor. Ejemplo:

# device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
# Add device specific permissions to hal_health_default domain, especially
# if it links to board-specific libhealthd or implements storage APIs.

Interfaces del kernel

El daemon healthd y la implementación predeterminada android.hardware.health@2.0-impl-2.1 acceden a las siguientes interfaces del kernel para recuperar información sobre la batería:

  • /sys/class/power_supply/*/capacity_level (agregado en Salud 2.1)
  • /sys/class/power_supply/*/capacity
  • /sys/class/power_supply/*/charge_counter
  • /sys/class/power_supply/*/charge_full
  • /sys/class/power_supply/*/charge_full_design (se agregó en Health 2.1)
  • /sys/class/power_supply/*/current_avg
  • /sys/class/power_supply/*/current_max
  • /sys/class/power_supply/*/current_now
  • /sys/class/power_supply/*/cycle_count
  • /sys/class/power_supply/*/health
  • /sys/class/power_supply/*/online
  • /sys/class/power_supply/*/present
  • /sys/class/power_supply/*/status
  • /sys/class/power_supply/*/technology
  • /sys/class/power_supply/*/temp
  • /sys/class/power_supply/*/time_to_full_now (se agregó en Health 2.1)
  • /sys/class/power_supply/*/type
  • /sys/class/power_supply/*/voltage_max
  • /sys/class/power_supply/*/voltage_now

Cualquier implementación de HAL de estado específica del dispositivo que use libbatterymonitor accede a estas interfaces de kernel de forma predeterminada, a menos que se anule en el constructor de la clase de implementación de salud.

Si faltan estos archivos o no se puede acceder a ellos desde healthd o desde el servicio predeterminado (por ejemplo, el archivo es un symlink a una carpeta específica del proveedor que niega el acceso debido a una política de SELinux mal configurada), es posible que no funcionen correctamente. Por lo tanto, es posible que se deban realizar cambios adicionales de SELinux específicos del proveedor, aunque se use la implementación predeterminada.

Es posible que algunas interfaces de kernel que se usan en Health 2.1, como /sys/class/power_supply/*/capacity_level y /sys/class/power_supply/*/time_to_full_now, sean opcionales. Sin embargo, para evitar comportamientos incorrectos del framework debido a la falta de interfaces de kernel, se recomienda seleccionar CL 1398913 antes de compilar el servicio HAL de Health 2.1.

Prueba

Android 11 incluye nuevas pruebas de VTS escritas específicamente para el HAL de health@2.1. Si un dispositivo declara el HAL de health@2.1 en el manifiesto del dispositivo, debe aprobar las pruebas de VTS correspondientes. Las pruebas se escriben para la instancia predeterminada (para garantizar que el dispositivo implemente el HAL correctamente) y la instancia de copia de seguridad (para garantizar que healthd siga funcionando correctamente antes de que se quite).

Requisitos de la información sobre la batería

El HAL de Health 2.0 establece un conjunto de requisitos en la interfaz de HAL, pero las pruebas de VTS correspondientes son relativamente flexibles en cuanto a su aplicación. En Android 11, se agregaron nuevas pruebas de VTS para aplicar los siguientes requisitos en los dispositivos que se inician con Android 11 y versiones posteriores:

  • Las unidades de la corriente instantánea y promedio de la batería deben ser microamperios (μA).
  • El signo de la corriente instantánea y promedio de la batería debe ser correcto. Específicamente:
    • current == 0 cuando el estado de la batería es UNKNOWN
    • Corriente superior a 0 cuando el estado de la batería es CHARGING
    • current <= 0 cuando el estado de la batería es NOT_CHARGING
    • Corriente inferior a 0 cuando el estado de la batería es DISCHARGING
    • No se aplica cuando el estado de la batería es FULL.
  • El estado de la batería debe ser correcto, independientemente de si hay o no una fuente de alimentación conectada. Específicamente:
    • El estado de la batería debe ser CHARGING, NOT_CHARGING o FULL solo si hay una fuente de alimentación conectada.
    • El estado de la batería debe ser DISCHARGING solo si se desconecta una fuente de alimentación.

Si usas libbatterymonitor en tu implementación y pasas valores desde las interfaces del kernel, asegúrate de que los nodos sysfs informen valores correctos:

  • Asegúrate de que la corriente de la batería se informe con el signo y las unidades correctos. Esto incluye los siguientes nodos sysfs:
    • /sys/class/power_supply/*/current_avg
    • /sys/class/power_supply/*/current_max
    • /sys/class/power_supply/*/current_now
    • Los valores positivos indican corriente entrante a la batería.
    • Los valores deben estar en microamperios (μA).
  • Asegúrate de que el voltaje de la batería se informe en microvoltios (μV). Esto incluye los siguientes nodos sysfs:
    • /sys/class/power_supply/*/voltage_max
    • /sys/class/power_supply/*/voltage_now
    • Ten en cuenta que la implementación predeterminada de HAL divide voltage_now por 1,000 y, luego, informa los valores en milivoltios (mV). Consulta @1.0::HealthInfo.

Para obtener más información, consulta Clase de fuente de alimentación de Linux.