RenderScript é uma estrutura para executar tarefas computacionalmente intensivas em alto desempenho no Android. Ele foi projetado para uso com computação paralela de dados, embora as cargas de trabalho seriais também possam se beneficiar. O tempo de execução do RenderScript paraleliza o trabalho entre os processadores disponíveis em um dispositivo, como CPUs e GPUs de vários núcleos, permitindo que os desenvolvedores se concentrem em expressar algoritmos em vez de agendar o trabalho. RenderScript é especialmente útil para aplicativos que executam processamento de imagem, fotografia computacional ou visão computacional.
Os dispositivos que executam o Android 8.0 e superior usam a seguinte estrutura RenderScript e HALs de fornecedores:
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 criadas como parte da plataforma e são atualizadas à medida que osystem.img
é atualizado. No entanto, as libs em/system/lib/vndk-sp
são criadas para o fornecedor e não são atualizadas quando osystem.img
é atualizado (embora possam ser atualizados 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
) são vinculados às bibliotecas internas do RenderScript localizadas em/system/lib/vndk-sp
. Eles não podem ser vinculados a libs em/system/lib
porque libs 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 um OTA somente de estrutura impossível.
Projeto
As seções a seguir detalham o design do RenderScript no Android 8.0 e superior.
Bibliotecas RenderScript disponíveis para fornecedores
Esta seção lista as bibliotecas do RenderScript (conhecidas como Vendor NDK para Same-Process HALs ou VNDK-SP) que estão disponíveis para o código do fornecedor e que 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 libs que não estejam no VNDK-SP sejam usadas pelo código do fornecedor é imposta 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 Same-Process HALs (SP-HALs) , exceto RenderScript , são carregados dentro do namespace do vinculador sphal
. O RenderScript é carregado no namespace rs
específico do RenderScript, um local que permite uma aplicação um pouco mais flexível para as 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 libs 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 de retorno 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 principal implementação do framework RS) é diretamente dlopen
do namespace do vinculador padrão onde a versão da plataforma de libs 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 null mVendorDriverName
. libRSDriver.so
é (por padrão) dlopen
ed e o driver lib é carregado do namespace default
porque o chamador ( libRS_internal.so
) também é carregado no namespace default
.
Caminho da GPU
Para o caminho da GPU, o libRS_internal.so
é carregado de forma diferente. Primeiro, libRS.so
usa android.hardware.renderscript@1.0.so
(e seu libhidltransport.so
subjacente) 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
s 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 compilação OVERRIDE_RS_DRIVER
, que é incorporado à implementação RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp
). Este nome de driver é então dlopen
para o contexto RS para o caminho da GPU.
A criação do objeto RsContext
é delegada à implementação do 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 então carrega o driver especificado quando o RsContext
é inicializado. Nesse caso, a biblioteca de 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 puder ser encontrada/carregada do namespace sphal
(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 bcc
bcc plugin
é uma biblioteca fornecida pelo fornecedor carregada no compilador bcc
. Como bcc
é um processo do sistema no diretório /system/bin
, a biblioteca de 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 um SP-HAL, a biblioteca bcc-plugin
:
- Não é possível vincular bibliotecas somente de estrutura, como
libLLVM.so
. - Pode vincular apenas as bibliotecas VNDK-SP disponíveis para o fornecedor.
Essa restrição é imposta 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()
por libLLVM.so
. No Android 8.0 e superior, isso é especificado na opção -plugin
e a lib é carregada diretamente pelo próprio bcc
. Essa opção habilita um caminho não específico do Android para o projeto LLVM de código aberto.
Pesquisar caminhos para ld.mc
Ao executar ld.mc
, algumas bibliotecas de tempo de execução RS são fornecidas como entradas para o vinculador. O código de bits RS do aplicativo é vinculado às bibliotecas de tempo de execução e quando o código de bits convertido é carregado em um processo de aplicativo, as bibliotecas de tempo de execução são novamente vinculadas dinamicamente a partir do código de bits convertido.
As bibliotecas de tempo de execução incluem:
-
libcompiler_rt.so
-
libm.so
-
libc.so
- Driver RS (seja
libRSDriver.so
ouOVERRIDE_RS_DRIVER
)
Ao carregar o bitcode compilado no processo do aplicativo, forneça exatamente a mesma biblioteca que foi 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 do framework RS e usando dladdr()
para obter o caminho do arquivo mapeado para o endereço.
Política SELinux
Como resultado das mudanças na política do SELinux no Android 8.0 e superior, você deve seguir regras específicas (impostas por neverallows
) ao rotular arquivos adicionais na partição do vendor
:
-
vendor_file
deve ser o rótulo padrão para todos os arquivos na partição dovendor
. A política da plataforma exige isso para acessar implementações de HAL de passagem. - Todos os novos
exec_types
adicionados na partição dovendor
por meio do fornecedor SEPolicy devem ter o atributovendor_file_type
. Isso é aplicado por meio deneverallows
. - Para evitar conflitos com futuras atualizações de plataforma/framework, evite rotular arquivos que não sejam
exec_types
na partição dovendor
. - Todas as dependências de biblioteca para HALs do mesmo processo identificadas por AOSP devem ser rotuladas como
same_process_hal_file
.
Para obter detalhes sobre a política do 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 haverá aumento de versão HAL, as estruturas RS continuarão usando o driver GPU existente (HAL 1.0).
Para pequenas alterações de HAL (HAL 1.1) que não afetam o código de bits, as estruturas devem retornar à CPU para essas APIs recém-adicionadas e continuar usando o driver GPU (HAL 1.0) em outros lugares.
Para grandes alterações de HAL (HAL 2.0) que afetam a compilação/vinculação de bitcode, as estruturas RS devem optar por não carregar drivers de GPU fornecidos pelo fornecedor e, em vez disso, usar o caminho da CPU ou Vulkan para aceleração.
O consumo de bitcode RenderScript ocorre em três estágios:
Etapa | Detalhes |
---|---|
Compilar |
|
Link |
|
Carga |
|
Além do HAL, as APIs de tempo de execução e os símbolos exportados também são interfaces. Nenhuma das interfaces foi alterada 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 for alterada, 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 o driver da GPU funcione corretamente.
Módulos de driver
- Os módulos de 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. - Implementação de 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 do RenderScript disponíveis para os fornecedores . - Invoque system bcc:
/system/bin/bcc
com umbcc plugin
fornecido pelo fornecedor; este plugin não pode depender de nenhuma biblioteca do 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 em 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
) em partição /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
da implementação RS HAL.
Política SELinux
A política do SELinux afeta os executáveis do driver e do compilador. Todos os módulos de driver devem ser rotulados 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 de 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 ao atualizar para o 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 fallback do tempo de execução do RenderScript para o 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 suspensão de uso incluem o seguinte:
- Migrar do Renderscript
- Amostra de migração RenderScript
- README do kit de ferramentas de substituição de intrínsecos
- Kit de ferramentas de substituição de intrínsecos.kt