Executar serviços da AIDL dinamicamente

A partir do Android 11, os serviços AIDL nativos em execução na partição do sistema podem ser iniciados e interrompidos dinamicamente conforme necessário. Os serviços dinâmicos começam quando são solicitados pela primeira vez e são interrompidos automaticamente quando não estão mais em uso.

Serviços que podem ser executados dinamicamente

Esse recurso está disponível apenas para serviços nativos cujo ciclo de vida pode ser controlado por init e servicemanager. Os serviços em pacotes de apps não têm suporte e precisam usar serviços vinculados.

O desligamento dinâmico funciona desativando o processo em que o serviço é executado. Se houver vários serviços no mesmo processo, todos eles precisam ser registrados como dinâmicos para serem compatíveis com esse recurso. Esse processo será encerrado quando todos os serviços deixarem de ser usados.

Configurar o arquivo .rc de inicialização de um serviço

Para executar um serviço dinamicamente, adicione as seguintes opções ao arquivo .rc de inicialização do serviço após a linha service <name> <cmd> inicial.

interface aidl serviceName
disabled
oneshot

Essas opções fazem o seguinte:

  • interface aidl serviceName: permite que servicemanager encontre o serviço. Se o serviço usar várias interfaces, declare cada uma delas em uma linha própria. Esses nomes precisam ser exatamente o que servicemanager espera e podem diferir do nome do processo.
  • disabled: impede que o serviço seja iniciado automaticamente na inicialização.
  • oneshot: impede que o serviço seja reinicializado automaticamente sempre que é interrompido.

Para mais informações, consulte o README da linguagem Android Init no AOSP.

Exemplos:

Registrar um serviço

Cada serviço é criado e registrado no servicemanager. O registro geralmente ocorre em um arquivo chamado main.cpp, mas a implementação pode variar. O registro geralmente tem esta aparência:

using android::defaultServiceManager;

defaultServiceManager()->addService(serviceName, service);

Às vezes, o registro é abstraído por BinderService::publish ou BinderService::instantiate, que chamam o código acima.

Para registrar um serviço como dinâmico, substitua o código de registro dele pelo seguinte:

#include <binder/LazyServiceRegistrar.h>

using android::binder::LazyServiceRegistrar;

auto lazyRegistrar = LazyServiceRegistrar::getInstance();
lazyRegistrar.registerService(service, serviceName);

O servicemanager se comunica com o LazyServiceRegistrar para encerrar os serviços com base nas contagens de referência.

Exemplos:

Configurar clientes de serviço AIDL

Acessar o serviço

Para recuperar um serviço lento, ele precisa ser iniciado e recuperado. Chamar getService no gerenciador de serviços iniciará o serviço, mas normalmente é melhor recebê-lo assim que ele estiver disponível, e é necessário usar as variantes waitForService. Consulte a documentação específica do back-end para saber como usá-los.

Liberar o serviço

O desligamento dinâmico é baseado na contagem de referências. Portanto, os clientes não podem manter o serviço quando ele não está em uso.

Exemplos:

Desativar temporariamente o desligamento

Se você quiser que um serviço seja executado de forma independente até que determinadas tarefas sejam concluídas e em seguida mude para o comportamento dinâmico, use LazyServiceRegistrar::forcePersist para ativar e desativar o desligamento dinâmico. Se ele for chamado do lado do servidor, ele precisará ser chamado antes de registerService.

Exemplo: apexservice