Decodificador e experiências com Android no contêiner LXC

Como surgiu uma necessidade estranha de rodar o Android em um contêiner Linux e o que veio dele

Antecedentes


Executar o Android no contêiner LXC, na minha opinião, é uma decisão lógica se você deseja ter transparência e confiabilidade do Bare Linux e usar o enorme potencial de aplicativos Android de terceiros bons (e não tão bons). Além disso, essa configuração é interessante como uma plataforma para depurar sua própria imagem AOSP em condições o mais próximo possível do combate.
Para os experimentos, um decodificador chinês progressivo e barato baseado no ARMv8 de 64 bits da Amlogic S905x foi selecionado (CPU - 4 núcleos, RAM - 2 GB, MMC - 8 GB). Além disso, um bom argumento (em comparação com outros fornecedores) foi a base de código no OpenSource e a presença do driver do kernel do Mali-450. Uma biblioteca de espaço para usuário do Mali hoje em domínio público no site oficial da ARM Limited. Bibliotecas de acesso binário para Linux-FB, Linux-Wayland e Android.

O principal objetivo dos experimentos foi a aplicação de cinemas e aplicativos on-line para trabalhar com hospedagem de mídia de rede. Por exemplo, com o Youtube no Linux, os problemas começaram imediatamente. Em primeiro lugar: o método hacker de obter links para o conteúdo analisando um script JS e gerando uma assinatura (anteriormente implementada no minitube da Tordini e no youtube-dl) começou a se deteriorar regularmente devido à luta impiedosa do Google com os métodos de rastreamento de anúncios. Segundo: a resolução máxima do conteúdo era de 720p - mais Google API não emitiu. Terceiro: o WebKit perdeu o suporte normal e recentemente foi suportado apenas por um pequeno grupo de entusiastas. O mesmo destino aconteceu com o seu porto Qt. Como resultado, em um ponto, a página do youtube / tv se recusou a funcionar, citando a idade avançada do mecanismo da web. Bem, no final, ele trouxe uma surpresa WebEngine (Qt-Chromium). Acontece que essa beleza não suporta aceleração de hardware. Uma exceção é feita apenas para sua porta Android e a ramificação marginal VAAPI no Linux. Beco sem saída. Em geral, não encontrei uma maneira simples de ativar a decodificação de vídeo acelerada por hardware para o Chromium no Linux. A implementação do VAAPI para Amlogic me pareceu um trabalho árduo e inútil. Eu também senti o plugin de pimenta - infelizmente o PPAPI não permite a reprodução de vídeo fora da tela.

Android


Por que não executar o Android em um contêiner? O projeto Anbox inspirou o feito. Um estudo aprofundado da Anbox mostrou que ela não nos convém. Mas a ideia era clara. Artigos de outros autores alegaram que executar o Android em um contêiner é uma tarefa idiota. Mas, de fato, tudo se tornou muito mais complicado. Simplesmente configurando os arquivos de configuração, não conseguimos sair.

Então, eu coleciono o LXC e o instalo no sistema. O teste de configuração do kernel revela problemas: você precisa habilitar o suporte ao espaço para nome. Como a plataforma é integrada, todos os tipos de coisas desnecessárias foram desativadas. Eu tive que identificar esses necessários desnecessários.

O primeiro teste foi verificar o Busybox no contêiner. Depois de garantir que tudo funcione, comecei a experimentar.

A visualização inicial é /var/lib/lxc/abox.conf:

lxc.rootfs = /var/lib/lxc/abox/rootfs lxc.rootfs.backend = dir lxc.utsname = abox lxc.pts = 1024 lxc.cap.drop = mac_admin mac_override 

Faça o download do AOSP 6.0.19 das mãos chinesas. Ele difere da versão baunilha pela presença de um iniciador normal, aguçado pelo distash e pelo navegador de superfície com suporte para alguns recursos da plataforma de hardware Amlogic. AOSP de baunilha também foi posteriormente testado.

Um pequeno desvio do tópico: os chineses, adaptando o software, cospem em todas as regras estabelecidas pela comunidade. Por exemplo, o kernel 3.14.29. Esse número de versão silenciosa do kernel é usado em quase todo hardware nos processadores Amlogic S8xx e S9xx. Mas, quase sempre, eles são muito diferentes um do outro, até a completa incompatibilidade de módulos antigos com novas imagens e vice-versa. Parece que o núcleo foi corrigido de acordo com o princípio: "o mais rápido possível a entrada do produto no mercado". O código não é apenas sujo - é de qualidade nojenta. Alterar a configuração geralmente leva a erros ao compilar ou vincular a imagem ou os módulos. O Android com patch é da mesma qualidade e os princípios de adaptação são semelhantes. Quase todas as recomendações da equipe AOSP são ignoradas.

Bem, nenhum lugar para ir! Nós coletamos.

Tentativa nº 1 Instale a imagem no contêiner, execute. Não funciona A análise mostra que não há objetos do kernel: fichário e ashmem. Nós adicionamos módulos do kernel.

Tentativa nº 2 Começamos novamente. O Installd trava. Acontece que o fichário original não conhece espaços para nome. Puxe o fichário da Anbox.

A tentativa número 3 inicia e imediatamente é reiniciada. Acontece que init quer o SELinux e se recusa a trabalhar sem ele.

Tentativa nº 4 Ligue o SELinux. Temos um monte de problemas para o sistema host. Eu tive que desligá-lo, pelo menos por enquanto - até que a essência e a teoria do processo fossem esclarecidas. O SELinux também pode ser desativado na linha de comando ao carregar o kernel, mas ainda não entendo como passar parâmetros para o contêiner. Eu tive que entrar na fonte init e corrigir aproximadamente seu comportamento. Esta foi a primeira e a última intervenção cirúrgica que me retornaram mais tarde.

Tentativa nº 5 O processo de inicialização chegou ao zigoto. Nos logs, jurando a partir do kernel no UID init. No fichário (e no fichário da Anbox), o UID do processo do proprietário é facilmente comparado à unidade. A única maneira é desativar a verificação, principalmente porque essa verificação não faz sentido no contêiner.

Tentativa nº 6 Surgiram conflitos relacionados ao compartilhamento de acesso ao gerenciamento de equipamentos. Comento os controles USB e Bluetooth nos scripts init. Eu removo todas as entradas do fstab e proíbo a montagem e a verificação de todas as mídias nos scripts. Agora adicione a placa de montagem à configuração do contêiner. Ele contém apenas uma linha. O diretório /mnt/lxc.data é montado no host em uma partição MMC real.

 lxc.mount.entry = /mnt/lxc.data data auto rw,bind 0 0 

Tentativa nº 7 As bolas saltitantes apareceram na tela, o download leva muito tempo, porque a imagem do Android está montada no NFS e o dexx também está sendo gerado no diretório / data. Recarregar é muitas vezes mais rápido. E, finalmente, o lançador apareceu.
Consideraremos isso a última tentativa, porque, em geral, tudo funciona e você precisa concluir os detalhes.

A rede não funciona, funciona com mais precisão, mas alguns aplicativos avaliam seu desempenho pelo estado das interfaces de rede. Mãos tortas, em uma palavra. Para eliminar essa desvantagem no host, aumentamos a ponte de rede (ponte) e a interface virtual (veth).

 lxc.network.type = veth lxc.network.flags = up lxc.network.name = eth1 lxc.network.link = br0 lxc.network.veth.pair = veth-01 lxc.network.ipv4 = 10.0.0.10/24 lxc.network.ipv4.gateway = 10.0.0.1 lxc.network.hwaddr = 00:FE:CD:BA:09:87 

Você também precisa aumentar o servidor DHCP, caso contrário, haverá problemas com o DNS. Infelizmente, o Android não analisa o resolv.conf e sua localização no sistema de arquivos não desempenha nenhum papel. Você pode configurar a conexão de rede manualmente, mas se você excluir os dados da seção de dados, todas as configurações serão redefinidas.

Sumário


Todos os aplicativos de estoque funcionam. Com instalado a partir do mercado, há problemas. Por exemplo: o Youtube.tv versão 3 exigiu a atualização da estrutura de serviço do Google, após o que o sistema travou. Surgiu um problema com o keystore (ainda não resolvido). O TEE também está temporariamente desativado, portanto o widevine não funciona. Brinquedos e aplicativos funcionam bem sem requisitos especiais de hardware. O Chrome torce o vídeo HTML5 com um decodificador de software, se recusa a conectar um decodificador de hardware. Nesta ocasião, há uma opinião sobre o AOSP distorcido pelos chineses. Mas o AOSP de baunilha lança um lançador com uma tela sensível ao toque - é impossível controlar a distacha.

Posfácio


Em um futuro próximo - para criar um iniciador para o lançamento de aplicativos Android diretamente do Linux. Um exemplo disso está disponível na fonte suplicante wpa. Você também pode espiar como isso é feito no Anbox.

Obrigado pela atenção!

Adição 1


Outro dia, verifiquei a escalabilidade dos aplicativos Qt. Inicialmente, o aplicativo cliente IPTV é escrito em QML para Linux. O player funciona através do plug-in QtMultimedia. Durante a compilação, surgiram dependências problemáticas. Felizmente, tudo estava limitado ao QtDbus, que não está no Android. Ainda não consigo entender por que o Android precisava reinventar o fichário. Do que os desenvolvedores do DBus não gostaram? Que funciona no espaço do usuário? Ou considerações sobre licenciamento?
DBus desconectado. Isso foi indolor, pois o canal era necessário para um pouco de funcionalidade relacionada ao sistema operacional. Reunidos apk. Não há nenhuma dificuldade com a montagem, pois eu uso o QtCreator (e eu o recomendo).
No AOSP, tive que desenhar uma ponte do Mediaplayer - um herdeiro do android :: MediaPlayerInterface. Os métodos setDataSource () e stop () foram implementados nele. Os plugues são feitos para o resto. setDataSource possui três interfaces. Foi necessário implementar apenas:
 setDataSource(const sp<IMediaHTTPService> &httpService, const char *uri, const KeyedVector<String8, String8> *headers) 


Se você deseja distorcer arquivos da mídia, precisa mexer com
 setDataSource(int fd, int64_t offset, int64_t length) 

O nome do arquivo precisará ser obtido através de "/ proc / self / fd /" + fd;

Após a instalação, o aplicativo ganhou e a transmissão foi. Ótimo! Eu esperava muitos problemas, mas não há quase nenhum. Obrigado aos desenvolvedores do Qt e QtCreator pelo excelente e útil trabalho!
Como resultado, consegui um monte: o player daemon host. No contêiner, há um programa cliente e uma faixa que transmite chamadas do android :: Mediaplayer para o host. O pacote funciona através de um soquete UDP.

Source: https://habr.com/ru/post/pt413809/


All Articles