HALs com disponibilidade dinâmica

O Android 9 oferece suporte ao desligamento dinâmico de subsistemas de hardware do Android quando eles não estão em uso ou não são necessários. Por exemplo, quando um usuário não está usando Wi-Fi, os subsistemas de Wi-Fi não podem ocupar memória, energia ou outros recursos do sistema. Em versões anteriores do Android, os HALs/drivers eram mantidos abertos em dispositivos Android durante todo o tempo em que um smartphone Android era inicializado.

A implementação do desligamento dinâmico envolve a conexão de fluxos de dados e a execução de processos dinâmicos, conforme detalhado nas seções a seguir.

Mudanças nas definições do HAL

O desligamento dinâmico requer informações sobre quais processos atendem a quais interfaces HAL (essas informações também podem ser úteis mais tarde em outros contextos) e não inicializam processos na inicialização e não os reiniciam (até que sejam solicitados novamente) quando saem.

# 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

Mudanças no init e hwservicemanager

O desligamento dinâmico também exige que o hwservicemanager diga init para iniciar os serviços solicitados. No Android 9, init inclui três mensagens de controle adicionais (por exemplo, ctl.start): ctl.interface_start, ctl.interface_stop e ctl.interface_restart. Essas mensagens podem ser usadas para sinalizar init para abrir e fechar interfaces de hardware específicas. Quando um serviço é solicitado e não está registrado, o hwservicemanager solicita que o serviço seja iniciado. No entanto, as HALs dinâmicas não exigem o uso de nenhuma delas.

Determinar a saída do HAL

No Android 9, a saída da HAL precisa ser determinada manualmente. No Android 10 e versões mais recentes, ele também pode ser determinado com ciclos de vida automáticos.

O desligamento dinâmico exige várias políticas para decidir quando iniciar e desligar uma HAL. Se um HAL decidir sair por qualquer motivo, ele será reiniciado automaticamente quando for necessário novamente usando as informações fornecidas na definição do HAL e a infraestrutura fornecida por mudanças em init e hwservicemanager. Isso pode envolver algumas estratégias diferentes, incluindo:

  • Um HAL pode optar por chamar a saída em si mesmo se alguém chamar uma API de fechamento ou semelhante. Esse comportamento precisa ser especificado na interface HAL correspondente.
  • Os HALs podem ser encerrados quando a tarefa é concluída (documentado no arquivo HAL).

Ciclos de vida automáticos

O Android 10 adiciona mais suporte ao kernel e hwservicemanager, o que permite que as HALs sejam desligadas automaticamente sempre que não tiverem clientes. Para usar esse recurso, siga todas as etapas em Alterações nas definições do HAL e também:

  • Registre o serviço em C++ com LazyServiceRegistrar em vez da função de membro, registerAsService, por exemplo:
    // only one instance of LazyServiceRegistrar per process
    LazyServiceRegistrar registrar;
    registrar.registerAsService(myHidlService /* , "default" */);
  • Verifique se o cliente HAL mantém uma referência ao HAL de nível superior (a interface registrada com hwservicemanager) somente quando ele está em uso. Para evitar atrasos, se essa referência for descartada em uma linha de execução hwbinder que continue sendo executada, o cliente também precisará chamar IPCThreadState::self()->flushCommands() após descartar a referência para garantir que o driver de vinculação seja notificado das mudanças associadas à contagem de referências.