Mudanças no ION ABI

Os dispositivos que enviam o kernel 4.14 e mais recentes são afetados por uma grande refatoração do módulo do kernel ION, que muitas implementações de camada de abstração de hardware (HAL) de alocador de memória gráfica (gralloc) do fornecedor chamam para alocar buffers de memória compartilhada. Esta página oferece orientações sobre como migrar o código do fornecedor legado para a nova versão do ION e discute possíveis interrupções futuras da interface binária de aplicativos (ABI).

Sobre o ION

O ION faz parte da árvore de preparo do kernel upstream. Durante o preparo, a ABI de espaço do usuário para kernel do ION pode ser interrompida entre as principais versões do kernel. Embora as interrupções ION ABI não afetem diretamente os apps comuns nem os dispositivos já iniciados, os fornecedores que migram para novas versões principais do kernel podem encontrar mudanças que afetam o código do fornecedor chamando o ION. Além disso, interrupções de ABI futuras podem ocorrer à medida que a equipe de sistemas do Android trabalha com upstream para mover o ION para fora da árvore de preparação.

Mudanças no android-4.14

O Kernel 4.12 refatorizou bastante o código do kernel ION, limpando e removendo partes do ION que se sobrepunham a outros frameworks do kernel. Como resultado, muitos ioctls ION legados não são mais relevantes e foram removidos.

Remoção de clientes e identificadores ION

Antes do kernel 4.12, a abertura de /dev/ion alocava um cliente ION. O ioctl ION_IOC_ALLOC alocou um novo buffer e o retornou ao espaço do usuário como um handle ION (um número inteiro opaco significativo apenas para o cliente ION que o alocou). Para mapear buffers no espaço do usuário ou compartilhá-los com outros processos, os identificadores ION foram reexportados como dma-buf fds usando o ioctl ION_IOC_SHARE.

No kernel 4.12, o ioctl ION_IOC_ALLOC gera diretamente dma-buf fds. O estado intermediário do identificador ION foi removido, junto com todos os ioctls que consomem ou produzem identificadores ION. Como o dma-buf fds não está vinculado a clientes ION específicos, o ioctl ION_IOC_SHARE não é mais necessário, e toda a infraestrutura de cliente ION foi removida.

Adição de ioctls de coerência do cache

Antes do kernel 4.12, o ION forneciava um ioctl ION_IOC_SYNC para sincronizar o descritor de arquivo com a memória. Esse ioctl era mal documentado e inflexível. Como resultado, muitos fornecedores implementaram ioctls personalizados para realizar a manutenção do cache.

O kernel 4.12 substituiu ION_IOC_SYNC pelo DMA_BUF_IOCTL_SYNC ioctl definido em linux/dma-buf.h. Chame DMA_BUF_IOCTL_SYNC no início e no final de cada acesso à CPU, com flags que especificam se esses acessos são leituras e/ou gravações. Embora DMA_BUF_IOCTL_SYNC seja mais detalhado do que ION_IOC_SYNC, ele oferece ao espaço do usuário mais controle sobre as operações de manutenção do cache subjacente.

DMA_BUF_IOCTL_SYNC faz parte da ABI estável do kernel e pode ser usado com todos os fds dma-buf, mesmo que tenham sido alocados pelo ION.

Como migrar o código do fornecedor para o Android 4.12 e versões mais recentes

Para clientes do userspace, a equipe de sistemas do Android recomenda o uso de libion em vez de codificar abertamente chamadas ioctl(). A partir do Android 9, o libion detecta automaticamente o ION ABI durante a execução e tenta mascarar quaisquer diferenças entre os kernels. No entanto, qualquer função do libion que tenha produzido ou consumido identificadores ion_user_handle_t não funciona mais após o kernel 4.12. É possível substituir essas funções pelas seguintes operações equivalentes em fds dma-buf, que funcionam em todas as versões do kernel até o momento.

Chamada ion_user_handle_t legada Chamada de fd de dma-buf equivalente
ion_alloc(ion_fd, …, &buf_handle) ion_alloc_fd(ion_fd, ..., &buf_fd)
ion_share(ion_fd, buf_handle, &buf_fd) N/A (essa chamada não é necessária com dma-buf fds)
ion_map(ion_fd, buf_handle, ...) mmap(buf_fd, ...)
ion_free(ion_fd, buf_handle) close(buf_fd)
ion_import(ion_fd, buf_fd, &buf_handle) N/A (essa chamada não é necessária com dma-buf fds)
ion_sync_fd(ion_fd, buf_fd)
If (ion_is_legacy(ion_fd))
    ion_sync_fd(ion_fd, buf_fd);
else
    ioctl(buf_fd, DMA_BUF_IOCTL_SYNC, ...);

Para clientes no kernel, como o ION não exporta mais nenhuma API voltada para o kernel, os drivers que usavam a API ION do kernel com ion_import_dma_buf_fd() precisam ser convertidos para usar a API dma-buf no kernel com dma_buf_get().

Futuros erros de ABI do ION

Antes que o ION possa ser removido da árvore de preparação, as versões futuras do kernel podem precisar quebrar a ABI do ION novamente. A equipe de sistemas do Android não espera que essas mudanças afetem os dispositivos lançados com a próxima versão do Android, mas elas podem afetar os dispositivos lançados com versões posteriores do Android.

Por exemplo, a comunidade upstream propôs dividir o único nó /dev/ion em vários nós por heap (por exemplo, /dev/ion/heap0) para permitir que os dispositivos apliquem políticas SELinux diferentes a cada heap. Se essa mudança for implementada em uma versão futura do kernel, ela vai interromper a ABI do ION.