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.