RenderScript é uma estrutura para executar tarefas computacionalmente intensivas com alto desempenho no Android. Ele foi projetado para uso com computação paralela de dados, embora cargas de trabalho seriais também possam se beneficiar. O tempo de execução do RenderScript paraleliza o trabalho entre processadores disponíveis em um dispositivo, como CPUs e GPUs multi-core, permitindo que os desenvolvedores se concentrem em expressar algoritmos em vez de agendar o trabalho. RenderScript é especialmente útil para aplicativos que realizam processamento de imagens, fotografia computacional ou visão computacional.
Dispositivos que executam o Android 8.0 e superior usam a seguinte estrutura RenderScript e HALs de fornecedor:
As diferenças do RenderScript no Android 7.xe inferior incluem:
- Duas instâncias de bibliotecas internas do RenderScript em um processo. Um conjunto é para o caminho de fallback da CPU e vem diretamente de
/system/lib
; o outro conjunto é para o caminho da GPU e é de/system/lib/vndk-sp
. - As bibliotecas internas do RS em
/system/lib
são construídas como parte da plataforma e são atualizadas à medida quesystem.img
é atualizado. No entanto, as bibliotecas em/system/lib/vndk-sp
são criadas para o fornecedor e não são atualizadas quandosystem.img
é atualizado (embora possam ser atualizadas para uma correção de segurança, sua ABI permanece a mesma). - O código do fornecedor (RS HAL, driver RS e o
bcc plugin
) estão vinculados às bibliotecas internas do RenderScript localizadas em/system/lib/vndk-sp
. Eles não podem vincular-se a bibliotecas em/system/lib
porque as bibliotecas nesse diretório são construídas para a plataforma e, portanto, podem não ser compatíveis com o código do fornecedor (ou seja, os símbolos podem ser removidos). Fazer isso tornaria impossível uma OTA apenas de estrutura.
Projeto
As seções a seguir detalham o design do RenderScript no Android 8.0 e versões posteriores.
Bibliotecas RenderScript disponíveis para fornecedores
Esta seção lista as bibliotecas RenderScript (conhecidas como Vendor NDK para Same-Process HALs ou VNDK-SP) que estão disponíveis para o código do fornecedor e às quais podem ser vinculadas. Ele também detalha bibliotecas adicionais que não estão relacionadas ao RenderScript, mas que também são fornecidas ao código do fornecedor.
Embora a lista de bibliotecas a seguir possa diferir entre as versões do Android, ela é imutável para uma versão específica do Android; para obter uma lista atualizada de bibliotecas disponíveis, consulte /system/etc/ld.config.txt
.
Bibliotecas RenderScript | Bibliotecas não RenderScript |
---|---|
|
|
Configuração do namespace do vinculador
A restrição de vinculação que impede que bibliotecas que não estão no VNDK-SP sejam usadas pelo código do fornecedor é aplicada em tempo de execução usando o namespace do vinculador. (Para obter detalhes, consulte a apresentação do VNDK Design .)
Em um dispositivo com Android 8.0 e superior, todos os HALs do mesmo processo (SP-HALs), exceto RenderScript, são carregados dentro do namespace do vinculador sphal
. O RenderScript é carregado no namespace específico do RenderScript rs
, um local que permite uma aplicação um pouco mais flexível para bibliotecas do RenderScript. Como a implementação RS precisa carregar o bitcode compilado, /data/*/*.so
é adicionado ao caminho do namespace rs
(outros SP-HALs não têm permissão para carregar bibliotecas da partição de dados).
Além disso, o namespace rs
permite mais bibliotecas do que as fornecidas por outros namespaces. libmediandk.so
e libft2.so
são expostos ao namespace rs
porque libRS_internal.so
tem uma dependência interna dessas bibliotecas.
Carregando drivers
Caminho alternativo da CPU
Dependendo da existência do bit RS_CONTEXT_LOW_LATENCY
ao criar um contexto RS, o caminho da CPU ou da GPU é selecionado. Quando o caminho da CPU é selecionado, libRS_internal.so
(a implementação principal da estrutura RS) é diretamente dlopen
a partir do namespace do vinculador padrão onde a versão da plataforma das bibliotecas RS é fornecida.
A implementação RS HAL do fornecedor não é usada quando o caminho de fallback da CPU é usado e um objeto RsContext
é criado com mVendorDriverName
nulo. libRSDriver.so
é (por padrão) dlopen
ed e o driver lib é carregado a partir do namespace default
porque o chamador ( libRS_internal.so
) também é carregado no namespace default
.
Caminho da GPU
Para o caminho da GPU, libRS_internal.so
é carregado de forma diferente. Primeiro, libRS.so
usa android.hardware.renderscript@1.0.so
(e seu subjacente libhidltransport.so
) para carregar android.hardware.renderscript@1.0-impl.so
(uma implementação de fornecedor de RS HAL) em um namespace de vinculador diferente chamado sphal
. O RS HAL então dlopen
libRS_internal.so
em outro namespace do vinculador chamado rs
.
Os fornecedores podem fornecer seu próprio driver RS definindo o sinalizador de tempo de construção OVERRIDE_RS_DRIVER
, que está incorporado na implementação RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp
). Este nome de driver é então dlopen
para o contexto RS do caminho da GPU.
A criação do objeto RsContext
é delegada à implementação RS HAL. O HAL chama de volta para a estrutura RS usando a função rsContextCreateVendor()
com o nome do driver a ser usado como argumento. A estrutura RS carrega o driver especificado quando o RsContext
é inicializado. Nesse caso, a biblioteca do driver é carregada no namespace rs
porque o objeto RsContext
é criado dentro do namespace rs
e /vendor/lib
está no caminho de pesquisa do namespace.
Ao fazer a transição do namespace default
para o namespace sphal
, libhidltransport.so
usa a função android_load_sphal_library()
para ordenar explicitamente que o vinculador dinâmico carregue a biblioteca -impl.so
do namespace sphal
.
Ao fazer a transição do namespace sphal
para o namespace rs
, o carregamento é feito indiretamente pela seguinte linha em /system/etc/ld.config.txt
:
namespace.sphal.link.rs.shared_libs = libRS_internal.so
Esta linha especifica que o vinculador dinâmico deve carregar libRS_internal.so
do namespace rs
quando a lib não pode ser encontrada/carregada do namespace sphal
(o que é sempre o caso porque o namespace sphal
não pesquisa /system/lib/vndk-sp
onde libRS_internal.so
reside). Com esta configuração, uma simples chamada dlopen()
para libRS_internal.so
é suficiente para fazer a transição do namespace.
Carregando plug-in Cco
bcc plugin
é uma biblioteca fornecida pelo fornecedor carregada no compilador bcc
. Como bcc
é um processo do sistema no diretório /system/bin
, a biblioteca bcc plugin
pode ser considerada um SP-HAL (ou seja, um HAL de fornecedor que pode ser carregado diretamente no processo do sistema sem ser vinculado). Como SP-HAL, a biblioteca bcc-plugin
:
- Não é possível vincular bibliotecas somente de estrutura, como
libLLVM.so
. - Pode vincular apenas às bibliotecas VNDK-SP disponíveis para o fornecedor.
Esta restrição é aplicada carregando o bcc plugin
no namespace sphal
usando a função android_sphal_load_library()
. Nas versões anteriores do Android, o nome do plugin era especificado usando a opção -load
e a lib era carregada usando o simples dlopen()
de libLLVM.so
. No Android 8.0 e superior, isso é especificado na opção -plugin
e a lib é carregada diretamente pelo próprio bcc
. Esta opção permite um caminho não específico do Android para o projeto LLVM de código aberto.
Caminhos de pesquisa para ld.mc
Ao executar ld.mc
, algumas bibliotecas de tempo de execução RS são fornecidas como entradas para o vinculador. O bitcode RS do aplicativo é vinculado às bibliotecas de tempo de execução e quando o bitcode convertido é carregado em um processo do aplicativo, as bibliotecas de tempo de execução são novamente vinculadas dinamicamente a partir do bitcode convertido.
As bibliotecas de tempo de execução incluem:
-
libcompiler_rt.so
-
libm.so
-
libc.so
- Driver RS (
libRSDriver.so
ouOVERRIDE_RS_DRIVER
)
Ao carregar o bitcode compilado no processo do aplicativo, forneça exatamente a mesma biblioteca usada por ld.mc
. Caso contrário, o bitcode compilado pode não encontrar um símbolo que estava disponível quando foi vinculado.
Para fazer isso, a estrutura RS usa diferentes caminhos de pesquisa para as bibliotecas de tempo de execução ao executar ld.mc
, dependendo se a própria estrutura RS é carregada de /system/lib
ou de /system/lib/vndk-sp
. Isso pode ser determinado lendo o endereço de um símbolo arbitrário de uma biblioteca de estrutura RS e usando dladdr()
para obter o caminho do arquivo mapeado para o endereço.
Política SELinux
Como resultado das alterações na política do SELinux no Android 8.0 e versões posteriores, você deve seguir regras específicas (aplicadas por meio de neverallows
) ao rotular arquivos adicionais na partição vendor
:
-
vendor_file
deve ser o rótulo padrão para todos os arquivos na partiçãovendor
. A política da plataforma exige isso para acessar implementações HAL de passagem. - Todos os novos
exec_types
adicionados na partiçãovendor
por meio do SEPolicy do fornecedor devem ter o atributovendor_file_type
. Isso é aplicado por meioneverallows
. - Para evitar conflitos com futuras atualizações de plataforma/estrutura, evite rotular arquivos que não sejam
exec_types
na partiçãovendor
. - Todas as dependências de biblioteca para HALs do mesmo processo identificados pelo AOSP devem ser rotuladas como
same_process_hal_file
.
Para obter detalhes sobre a política SELinux, consulte Linux com segurança aprimorada no Android .
Compatibilidade ABI para bitcode
Se nenhuma nova API for adicionada, o que significa que não há aumento de versão do HAL, as estruturas RS continuarão usando o driver GPU (HAL 1.0) existente.
Para pequenas alterações de HAL (HAL 1.1) que não afetem o bitcode, as estruturas devem recorrer à CPU para essas APIs recém-adicionadas e continuar usando o driver GPU (HAL 1.0) em outro lugar.
Para grandes alterações de HAL (HAL 2.0) que afetam a compilação/vinculação de código de bits, as estruturas RS devem optar por não carregar drivers de GPU fornecidos pelo fornecedor e, em vez disso, usar a CPU ou o caminho Vulkan para aceleração.
O consumo do bitcode RenderScript ocorre em três etapas:
Estágio | Detalhes |
---|---|
Compilar |
|
Link |
|
Carregar |
|
Além do HAL, as APIs de tempo de execução e os símbolos exportados também são interfaces. Nenhuma das interfaces mudou desde o Android 7.0 (API 24) e não há planos imediatos para alterá-la no Android 8.0 e posteriores. No entanto, se a interface mudar, a versão HAL também será incrementada.
Implementações de fornecedores
O Android 8.0 e superior requer algumas alterações no driver da GPU para que ele funcione corretamente.
Módulos de driver
- Os módulos do driver não devem depender de nenhuma biblioteca do sistema que não esteja na lista .
- O driver deve fornecer seu próprio
android.hardware.renderscript@1.0-impl_{NAME}
ou declarar a implementação padrãoandroid.hardware.renderscript@1.0-impl
como sua dependência. - A implementação da CPU
libRSDriver.so
é um bom exemplo de como remover dependências não VNDK-SP.
Compilador de código de bits
Você pode compilar o bitcode RenderScript para o driver do fornecedor de duas maneiras:
- Invoque o compilador RenderScript específico do fornecedor em
/vendor/bin/
(método preferencial de compilação de GPU). Semelhante a outros módulos de driver, o binário do compilador do fornecedor não pode depender de nenhuma biblioteca do sistema que não esteja na lista de bibliotecas RenderScript disponíveis para os fornecedores . - Invoque o sistema bcc:
/system/bin/bcc
com umbcc plugin
fornecido pelo fornecedor; este plugin não pode depender de nenhuma biblioteca de sistema que não esteja na lista de bibliotecas RenderScript disponíveis para fornecedores .
Se o bcc plugin
do fornecedor precisar interferir na compilação da CPU e sua dependência de libLLVM.so
não puder ser facilmente removida, o fornecedor deverá copiar bcc
(e todas as dependências não LL-NDK, incluindo libLLVM.so
, libbcc.so
) para /vendor
.
Além disso, os fornecedores precisam fazer as seguintes alterações:
- Copie
libclcore.bc
para a partição/vendor
. Isso garantelibclcore.bc
,libLLVM.so
elibbcc.so
estejam sincronizados. - Altere o caminho para o executável
bcc
definindoRsdCpuScriptImpl::BCC_EXE_PATH
na implementação RS HAL.
Política SELinux
A política SELinux afeta o driver e os executáveis do compilador. Todos os módulos de driver devem ser rotulados como same_process_hal_file
no file_contexts
do dispositivo. Por exemplo:
/vendor/lib(64)?/libRSDriver_EXAMPLE\.so u:object_r:same_process_hal_file:s0
O executável do compilador deve poder ser invocado por um processo de aplicativo, assim como a cópia do fornecedor do bcc ( /vendor/bin/bcc
). Por exemplo:
device/vendor_foo/device_bar/sepolicy/file_contexts: /vendor/bin/bcc u:object_r:same_process_hal_file:s0
Dispositivos legados
Dispositivos legados são aqueles que atendem às seguintes condições:
- PRODUCT_SHIPPING_API_LEVEL é inferior a 26.
- PRODUCT_FULL_TREBLE_OVERRIDE não está definido.
Para dispositivos legados, as restrições não são aplicadas durante a atualização para Android 8.0 e superior, o que significa que os drivers podem continuar vinculados a bibliotecas em /system/lib[64]
. No entanto, devido à mudança de arquitetura relacionada a OVERRIDE_RS_DRIVER
, android.hardware.renderscript@1.0-impl
deve ser instalado na partição /vendor
; não fazer isso força o retorno do tempo de execução do RenderScript ao caminho da CPU.
Para obter informações sobre a motivação para a descontinuação do Renderscript, consulte o Android Developers Blog: Android GPU Compute Going Forward . As informações de recursos para esta descontinuação incluem o seguinte:
- Migrar do Renderscript
- Amostra de RenderScriptMigration
- README do kit de ferramentas de substituição intrínseca
- Kit de ferramentas de substituição intrínseca.kt