O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Usando Binder IPC

Esta página descreve as mudanças no driver do binder no Android 8, fornece detalhes sobre o uso do IPC do binder e lista a política SELinux necessária.

Mudanças no driver do fichário

A partir do Android 8, a estrutura do Android e os HALs agora se comunicam usando o fichário. Como essa comunicação aumenta drasticamente o tráfego do fichário, o Android 8 inclui várias melhorias projetadas para manter o IPC fichário rápido. Os fornecedores de SoC e OEMs devem se fundir diretamente a partir das ramificações relevantes do android-4.4, android-4.9 e superior do kernel / projeto comum .

Vários domínios de fichário (contextos)

Common-4.4 e superior, incluindo upstream

Para dividir de forma limpa o tráfego do fichário entre o código da estrutura (independente do dispositivo) e o código do fornecedor (específico do dispositivo), o Android 8 introduziu o conceito de um contexto do fichário . Cada contexto de fichário tem seu próprio nó de dispositivo e seu próprio gerenciador de contexto (serviço). Você pode acessar o gerenciador de contexto apenas através do nó do dispositivo ao qual ele pertence e, ao passar um nó do binder por um determinado contexto, ele é acessível a partir desse mesmo contexto apenas por outro processo, isolando assim completamente os domínios uns dos outros. Para obter detalhes sobre como usar, consulte vndbinder e vndservicemanager .

Scatter-reunir

Common-4.4 e superior, incluindo upstream

Nas versões anteriores do Android, todos os dados em uma chamada de fichário eram copiados três vezes:

  • Uma vez para serializá-lo em um Parcel no processo de chamada
  • Uma vez no driver do kernel para copiar o Parcel para o processo de destino
  • Uma vez para desserializar o Parcel no processo de destino

O Android 8 usa otimização de dispersão para reduzir o número de cópias de 3 para 1. Em vez de serializar os dados em um Parcel primeiro, os dados permanecem em sua estrutura original e layout de memória e o driver os copia imediatamente para o processo de destino. Depois que os dados estão no processo de destino, a estrutura e o layout da memória são os mesmos e os dados podem ser lidos sem a necessidade de outra cópia.

Travamento refinado

Common-4.4 e superior, incluindo upstream

Em versões anteriores do Android, o driver do binder usava um bloqueio global para proteger contra o acesso simultâneo a estruturas de dados críticas. Embora houvesse contenção mínima para o bloqueio, o principal problema era que se um encadeamento de baixa prioridade obtivesse o bloqueio e fosse interrompido, ele poderia atrasar seriamente os encadeamentos de alta prioridade que precisavam obter o mesmo bloqueio. Isso causou solavanco na plataforma.

As tentativas iniciais de resolver esse problema envolviam a desativação da preempção enquanto mantinha o bloqueio global. No entanto, isso foi mais um hack do que uma solução verdadeira, e acabou sendo rejeitado pelo upstream e descartado. As tentativas subsequentes se concentraram em tornar o bloqueio mais refinado, uma versão que está em execução em dispositivos Pixel desde janeiro de 2017. Embora a maioria dessas alterações tenha sido tornada pública, melhorias substanciais foram feitas nas versões subsequentes.

Depois de identificar pequenos problemas na implementação de bloqueio de baixa granularidade, criamos uma solução aprimorada com uma arquitetura de bloqueio diferente e enviamos as alterações em todos os ramos comuns do kernel. Continuamos testando essa implementação em um grande número de dispositivos diferentes; como não temos conhecimento de quaisquer problemas pendentes, esta é a implementação recomendada para dispositivos que vêm com Android 8.

Herança de prioridade em tempo real

Common-4.4 e common-4.9 (upstream em breve)

O driver do fichário sempre suportou uma boa herança de prioridade. Como um número crescente de processos no Android é executado em prioridade em tempo real, em alguns casos agora faz sentido que, se um encadeamento em tempo real fizer uma chamada de fichário, o encadeamento no processo que lida com essa chamada também será executado em prioridade em tempo real . Para oferecer suporte a esses casos de uso, o Android 8 agora implementa a herança de prioridade em tempo real no driver do fichário.

Além da herança de prioridade de nível de transação, a herança de prioridade de permite que um nó (objeto de serviço de fichário) especifique uma prioridade mínima na qual as chamadas para este nó devem ser executadas. As versões anteriores do Android já suportavam a herança de prioridade de nó com bons valores, mas o Android 8 adiciona suporte para herança de nó de políticas de agendamento em tempo real.

Mudanças no espaço do usuário

O Android 8 inclui todas as alterações de espaço do usuário necessárias para funcionar com o driver de fichário atual no kernel comum, com uma exceção: a implementação original para desabilitar a herança de prioridade em tempo real para /dev/binder usou um ioctl . O desenvolvimento subsequente mudou o controle de herança de prioridade para um método mais refinado que é por modo de fichário (e não por contexto). Portanto, o ioctl não está no branch comum do Android e, em vez disso, é enviado em nossos kernels comuns .

O efeito dessa mudança é que a herança de prioridade em tempo real é desabilitada por padrão para cada nó. A equipe de desempenho do Android achou benéfico habilitar a herança de prioridade em tempo real para todos os nós no domínio hwbinder . Para obter o mesmo efeito, escolha a dedo essa mudança no espaço do usuário.

SHAs para kernels comuns

Para obter as alterações necessárias no driver do fichário, sincronize com o SHA apropriado:

  • Common-3.18
    cc8b90c121de ANDROID: fichário: não verifica as permissões de prio ao restaurar.
  • Common-4.4
    76b376eac7a2 ANDROID: fichário: não verifica as permissões prio na restauração.
  • Comum-4.9
    ecd972d4f9b5 ANDROID: binder: não verifica as permissões prio na restauração.

Usando aglutinante IPC

Historicamente, os processos do fornecedor têm usado a comunicação entre processos do binder (IPC) para se comunicar. No Android 8, o nó do dispositivo /dev/binder torna-se exclusivo para processos de estrutura, o que significa que os processos do fornecedor não têm mais acesso a ele. Os processos do fornecedor podem acessar /dev/hwbinder , mas devem converter suas interfaces AIDL para usar HIDL. Para fornecedores que desejam continuar usando interfaces AIDL entre processos de fornecedores, o Android oferece suporte a IPC de fichário conforme descrito abaixo.

vndbinder

O Android 8 oferece suporte a um novo domínio de fichário para uso por serviços de fornecedores, acessado usando /dev/vndbinder vez de /dev/binder . Com a adição de /dev/vndbinder , o Android agora tem os três domínios IPC a seguir:

Domínio IPC Descrição
/dev/binder IPC entre processos de framework / aplicativo com interfaces AIDL
/dev/hwbinder IPC entre processos de estrutura / fornecedor com interfaces HIDL
IPC entre os processos do fornecedor com interfaces HIDL
/dev/vndbinder IPC entre fornecedores / processos de fornecedores com interfaces AIDL

Para que /dev/vndbinder apareça, certifique-se de que o item de configuração do kernel CONFIG_ANDROID_BINDER_DEVICES esteja definido como "binder,hwbinder,vndbinder" (este é o padrão nas árvores de kernel comuns do Android).

Normalmente, os processos do fornecedor não abrem o driver do fichário diretamente e, em vez disso, são vinculados à biblioteca do espaço do usuário libbinder , que abre o driver do fichário. Adicionar um método para ::android::ProcessState() seleciona o driver do binder para libbinder . Os processos do fornecedor devem chamar esse método antes de chamar ProcessState, IPCThreadState ou antes de fazer qualquer chamada de binder em geral. Para usar, faça a seguinte chamada após o main() de um processo de fornecedor (cliente e servidor):

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

Anteriormente, os serviços do binder eram registrados no servicemanager , onde podiam ser recuperados por outros processos. No Android 8, o servicemanager agora é usado exclusivamente por processos de framework e aplicativo e os processos do fornecedor não podem mais acessá-lo.

No entanto, os serviços do fornecedor agora podem usar vndservicemanager , uma nova instância do servicemanager que usa /dev/vndbinder vez de /dev/binder e que é construída a partir das mesmas fontes do framework servicemanager . Os processos do fornecedor não precisam fazer alterações para falar com o vndservicemanager ; quando um processo de fornecedor abre / dev/vndbinder , as pesquisas de serviço vão automaticamente para vndservicemanager .

O binário vndservicemanager está incluído nos makefiles do dispositivo padrão do Android.

Política SELinux

Os processos do fornecedor que desejam usar a funcionalidade de fichário para se comunicarem precisam do seguinte:

  1. Acesso a /dev/vndbinder .
  2. Binder {transfer, call} conecta-se ao vndservicemanager .
  3. binder_call(A, B) para qualquer domínio do fornecedor A que deseja chamar o domínio do fornecedor B pela interface do fichário do fornecedor.
  4. Permissão para {add, find} serviços em vndservicemanager .

Para cumprir os requisitos 1 e 2, use a macro vndbinder_use() :

vndbinder_use(some_vendor_process_domain);

Para cumprir o requisito 3, o binder_call(A, B) para os processos do fornecedor A e B que precisam conversar sobre o fichário pode permanecer no lugar e não precisa ser renomeado.

Para cumprir o requisito 4, você deve fazer alterações na maneira como os nomes de serviço, rótulos de serviço e regras são tratados.

Para obter detalhes sobre o SELinux, consulte Security-Enhanced Linux in Android . Para obter detalhes sobre o SELinux no Android 8.0, consulte SELinux para Android 8.0 .

Nomes de serviço

Anteriormente, o fornecedor processava nomes de serviço registrados em um arquivo service_contexts e adicionava regras correspondentes para acessar esse arquivo. Exemplo de arquivo service_contexts de device/google/marlin/sepolicy :

AtCmdFwd                              u:object_r:atfwd_service:s0
cneservice                            u:object_r:cne_service:s0
qti.ims.connectionmanagerservice      u:object_r:imscm_service:s0
rcs                                   u:object_r:radio_service:s0
uce                                   u:object_r:uce_service:s0
vendor.qcom.PeripheralManager         u:object_r:per_mgr_service:s0

No Android 8, vndservicemanager carrega o arquivo vndservice_contexts . Os serviços do fornecedor migrando para vndservicemanager (e que já estão no arquivo service_contexts antigo) devem ser adicionados ao novo arquivo vndservice_contexts .

Rótulos de serviço

Anteriormente, rótulos de serviço como u:object_r:atfwd_service:s0 eram definidos em um arquivo service.te . Exemplo:

type atfwd_service,      service_manager_type;

No Android 8, você deve alterar o tipo para vndservice_manager_type e mover a regra para o arquivo vndservice.te . Exemplo:

type atfwd_service,      vndservice_manager_type;

Regras do Servicemanager

Anteriormente, as regras concediam aos domínios acesso para adicionar ou localizar serviços do servicemanager . Exemplo:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

No Android 8, essas regras podem permanecer em vigor e usar a mesma classe. Exemplo:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;