HAL disponibles dinámicamente

Android 9 admite el cierre dinámico de los subsistemas de hardware de Android cuando no están en uso o no son necesarios. Por ejemplo, cuando un usuario no usa Wi-Fi, los subsistemas de Wi-Fi no deben ocupar memoria, energía ni otros recursos del sistema. En versiones anteriores de Android, los HAL o los controladores se mantenían abiertos en los dispositivos Android durante todo el tiempo que se iniciaba un teléfono Android.

La implementación del cierre dinámico implica conectar flujos de datos y ejecutar procesos dinámicos, como se detalla en las siguientes secciones.

Cambios en las definiciones de HAL

El cierre dinámico requiere información sobre qué procesos entregan qué interfaces de HAL (esta información también puede ser útil más adelante en otros contextos), así como no iniciar procesos durante el inicio ni reiniciarlos (hasta que se vuelvan a solicitar) cuando salgan.

# some init.rc script associated with the HAL
service vendor.some-service-name /vendor/bin/hw/some-binary-service
    # init language extension, provides information of what service is served
    # if multiple interfaces are served, they can be specified one on each line
    interface android.hardware.light@2.0::ILight default
    # restarted if hwservicemanager dies
    # would also cause the hal to start early during boot if disabled wasn't set
    class hal
    # will not be restarted if it exits until it is requested to be restarted
    oneshot
    # will only be started when requested
    disabled
    # ... other properties

Cambios en init y hwservicemanager

El cierre dinámico también requiere que hwservicemanager le diga a init que inicie los servicios solicitados. En Android 9, init incluye tres mensajes de control adicionales (p.ej., ctl.start): ctl.interface_start, ctl.interface_stop y ctl.interface_restart. Estos mensajes se pueden usar para indicar a init que active o desactive interfaces de hardware específicas. Cuando se solicita un servicio y no está registrado, hwservicemanager solicita que se inicie. Sin embargo, los HAL dinámicos no requieren el uso de ninguno de estos.

Determina la salida de HAL

En Android 9, la salida de HAL se debe determinar de forma manual. En Android 10 y versiones posteriores, también se puede determinar con ciclos de vida automáticos.

El cierre dinámico requiere varias políticas para decidir cuándo iniciar un HAL y cuándo cerrarlo. Si un HAL decide salir por algún motivo, se reiniciará automáticamente cuando se vuelva a necesitar con la información proporcionada en la definición de HAL y la infraestructura proporcionada por los cambios en init y hwservicemanager. Esto podría implicar algunas estrategias diferentes, como las siguientes:

  • Un HAL podría elegir llamar a exit en sí mismo si alguien llama a una API de cierre o similar. Este comportamiento se debe especificar en la interfaz de HAL correspondiente.
  • Los HAL pueden cerrarse cuando se completa su tarea (documentada en el archivo HAL).

Ciclos de vida automáticos

Android 10 agrega más compatibilidad con el kernel y hwservicemanager, lo que permite que las HAL se cierren automáticamente cuando no tengan clientes. Para usar esta función, sigue todos los pasos que se indican en Cambios en las definiciones de HAL, además de lo siguiente:

  • Registra el servicio en C++ con LazyServiceRegistrar en lugar de la función miembro, registerAsService, por ejemplo:
    // only one instance of LazyServiceRegistrar per process
    LazyServiceRegistrar registrar;
    registrar.registerAsService(myHidlService /* , "default" */);
  • Verifica que el cliente de HAL mantenga una referencia al HAL de nivel superior (la interfaz registrada con hwservicemanager) solo cuando esté en uso. Para evitar demoras si esta referencia se descarta en un subproceso de hwbinder que sigue ejecutándose, el cliente también debe llamar a IPCThreadState::self()->flushCommands() después de descartar la referencia para asegurarse de que se notifique al controlador de Binder sobre los cambios asociados en el recuento de referencias.