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.
Alterações nas definições de HAL
O desligamento dinâmico requer informações sobre quais processos atendem a quais interfaces HAL (essas informações também podem ser úteis posteriormente em outros contextos), bem como não iniciar processos na inicialização e não reiniciá-los (até que sejam solicitados novamente) quando eles forem encerrados.
# 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 propertiesMudanças no init e no hwservicemanager
O desligamento dinâmico também requer que o hwservicemanager diga ao init para iniciar os serviços solicitados. No Android 9, o 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 o init para ativar e desativar interfaces de hardware específicas. Quando um serviço é solicitado e não é registrado, o hwservicemanager solicita que o serviço seja iniciado. No entanto, os HALs dinâmicos não exigem o uso de nenhum deles.
Determinando a saída HAL
No Android 9, a saída HAL deve ser determinada manualmente. Para Android 10 e superior, também pode ser determinado com ciclos de vida automáticos .
O desligamento dinâmico requer várias políticas para decidir quando iniciar um HAL e quando encerrar um 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 de HAL e a infraestrutura fornecida pelas alterações no init e hwservicemanager . Isso pode envolver algumas estratégias diferentes, incluindo:
- Um HAL pode optar por chamar exit em si mesmo se alguém chamar uma API próxima ou semelhante nele. Esse comportamento deve ser especificado na interface HAL correspondente.
- Os HALs podem ser encerrados quando sua tarefa for 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 os HALs sejam desligados automaticamente sempre que não tiverem clientes. Para usar esse recurso, execute todas as etapas em Alterações nas definições de HAL , bem como:
- Registre o serviço em C++ com
LazyServiceRegistrarem 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 está em uso. Para evitar atrasos se esta referência for descartada em um thread hwbinder que continua a ser executado, o cliente também deve chamarIPCThreadState::self()->flushCommands()após descartar a referência para garantir que o driver do binder seja notificado da contagem de referência associada mudanças.