Set-Top-Box et expériences avec Android dans le conteneur LXC

Comment un besoin étrange est apparu pour exécuter Android dans un conteneur Linux, et ce qui en est ressorti

Contexte


Exécuter Android dans le conteneur LXC, à mon avis, est une décision logique si vous voulez avoir la transparence et la fiabilité de Bare Linux et utiliser l'énorme potentiel des bonnes applications Android tierces (et pas si bonnes). De plus, cette configuration est intéressante en tant que plate-forme pour déboguer votre propre image AOSP dans des conditions aussi proches que possible du combat.
Pour les expériences, un décodeur chinois progressif et peu coûteux basé sur ARMv8 64 bits d'Amlogic S905x a été sélectionné (CPU - 4 cœurs, RAM - 2 Go, MMC - 8 Go). En outre, un bon argument (par rapport à d'autres fournisseurs) était la base de code dans OpenSource et la présence du pilote du noyau du noyau source pour Mali-450. Une bibliothèque de l'espace utilisateur Mali aujourd'hui dans le domaine public sur le site officiel d'ARM Limited. Bibliothèques d'accès binaires pour Linux-FB, Linux-Wayland et Android.

Le but principal des expériences était l'application de cinémas en ligne et d'applications pour travailler avec l'hébergement multimédia en réseau. Par exemple, avec Youtube sur Linux, les problèmes ont commencé tout de suite. Premièrement: la méthode de piratage pour obtenir des liens vers du contenu en analysant un script JS et en générant une signature (précédemment implémentée dans le minitube de Tordini et dans youtube-dl) a commencé à tomber en panne régulièrement en raison de la lutte sans merci de Google avec les méthodes d'exploration des annonces. Deuxièmement: la résolution maximale du contenu était de 720p - plus de Google-API n'a pas été émis. Troisièmement: WebKit a perdu un support normal et n'a été récemment pris en charge que par un petit groupe de passionnés. Le même sort est arrivé à son port Qt. En conséquence, à un moment donné, la page YouTube / TV a refusé de fonctionner, citant la vieillesse du moteur Web. Eh bien, à la fin, il a créé un WebEngine surprise (Qt-Chromium). Il s'avère que cette beauté ne prend pas en charge l'accélération matérielle. Une exception est faite uniquement pour son port Android et la branche VAAPI marginale sous Linux. Impasse. En général, je n'ai pas trouvé de moyen simple d'activer le décodage vidéo accéléré par matériel pour Chromium sous Linux. L'implémentation de VAAPI pour Amlogic m'a semblé un travail difficile et inutile. J'ai également ressenti le plugin pepper - malheureusement PPAPI ne permet pas de lire des vidéos hors écran.

Android


Pourquoi ne pas exécuter Android dans un conteneur? Le projet Anbox a inspiré l'exploit. Une étude approfondie d'Anbox a montré que cela ne nous convenait pas. Mais l'idée était claire. Des articles d'autres auteurs ont affirmé que l'exécution d'Android dans un conteneur est une tâche stupide. Mais en fait, tout s'est avéré beaucoup plus compliqué. En configurant simplement les fichiers de configuration, nous n'avons pas pu descendre.

Donc, je récupère LXC et l'installe dans le système. Le test de configuration du noyau révèle des problèmes: vous devez activer la prise en charge de l'espace de noms. Étant donné que la plate-forme est intégrée, toutes sortes de choses inutiles ont été désactivées. J'ai dû identifier ces nécessaires inutiles.

Le premier test consistait à vérifier Busybox dans le conteneur. Après m'être assuré que tout fonctionne, j'ai commencé à expérimenter.

La vue initiale est /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 

Téléchargez le butin chinois mains AOSP 6.0.19. Il diffère de la version vanille par la présence d'un lanceur normal, aiguisé par distash et surfacelinger corrigé avec prise en charge de certaines fonctionnalités de la plate-forme matérielle Amlogic. La vanille AOSP a ensuite été également testée.

Un petit écart par rapport au sujet: les Chinois, adaptant le logiciel, crachent sur toutes les règles établies par la communauté. Par exemple, le noyau 3.14.29. Ce numéro de version du noyau silencieux est utilisé sur presque tous les matériels des processeurs Amlogic S8xx et S9xx. Mais, presque toujours, ils sont très différents les uns des autres, jusqu'à l'incompatibilité complète des anciens modules avec les nouvelles images et vice versa. Il semble que le noyau ait été corrigé selon le principe: «le plus rapidement possible l’entrée du produit sur le marché». Le code n'est pas seulement sale - il est d'une qualité dégoûtante. La modification de la configuration entraîne généralement des erreurs lors de la compilation ou de la liaison de l'image ou des modules. Android patché est de la même qualité et les principes d'adaptation sont similaires. Presque toutes les recommandations de l'équipe AOSP sont ignorées.

Eh bien, nulle part où aller! Nous collectons.

Tentative n ° 1 Installez l'image dans le conteneur, exécutez. Ne marche pas. L'analyse montre qu'il n'y a pas d'objets noyau: liant et ashmem. Nous ajoutons des modules du noyau.

Tentative n ° 2 Nous recommençons. Installd plante. Il s'avère que le classeur d'origine ne connaît pas les espaces de noms. Tirez le classeur d'Anbox.

La tentative numéro 3 démarre et va immédiatement redémarrer. Il s'avère qu'init veut SELinux et refuse de travailler sans lui.

Tentative n ° 4 Activez SELinux. Nous obtenons un tas de problèmes pour le système hôte. J'ai dû le désactiver, du moins pour l'instant - jusqu'à ce que l'essence et la théorie du processus soient clarifiées. SELinux peut également être désactivé sur la ligne de commande lors du chargement du noyau, mais je ne comprends toujours pas comment transmettre des paramètres au conteneur. J'ai dû entrer dans la source init et corriger grossièrement son comportement. Ce fut la première et la dernière intervention chirurgicale qui me revint plus tard.

Tentative n ° 5 Le processus de démarrage a atteint le zygote. Dans les journaux, jure du noyau sur l'init de l'UID. Dans le classeur (et le classeur d'Anbox), l'UID du processus propriétaire est facilement comparable à l'unité. La seule façon est de désactiver la vérification, d'autant plus que cette vérification n'a pas de sens dans le conteneur.

Tentative n ° 6 Des conflits liés au partage de l'accès à la gestion des équipements sont apparus. Je commente les commandes USB et Bluetooth dans les scripts d'initialisation. Je supprime toutes les entrées de fstab et interdit le montage et la vérification de tous les médias dans les scripts. Ajoutez maintenant la carte de montage à la configuration du conteneur. Il ne contient qu'une seule ligne. Le répertoire /mnt/lxc.data est monté sur l'hôte dans une véritable partition MMC.

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

Tentative n ° 7 Des balles rebondissantes sont apparues à l'écran, le chargement prend beaucoup de temps, car l'image Android est montée sur NFS, et dexx est également généré dans le répertoire / data. Le rechargement est plusieurs fois plus rapide. Et enfin, le lanceur est apparu.
Nous considérerons cela comme la dernière tentative, car, en général, tout fonctionne et vous devez terminer les détails.

Le réseau ne fonctionne pas, il fonctionne plus précisément, mais certaines applications évaluent ses performances par l'état des interfaces réseau. Des mains tordues, en un mot. Pour éliminer cet inconvénient sur l'hôte, nous élevons le pont réseau (bridge) et l'interface virtuelle (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 

Vous devez également augmenter le serveur DHCP, sinon il y aura des problèmes avec DNS. Malheureusement, Android n'analyse pas resolv.conf et son emplacement dans le système de fichiers ne joue aucun rôle. Vous pouvez configurer la connexion réseau manuellement, mais si vous supprimez des données de la section des données, tous les paramètres seront réinitialisés.

Résumé


Toutes les applications de stock fonctionnent. Avec installé sur le marché, il y a des problèmes. Par exemple: Youtube.tv version 3 a demandé de mettre à jour le cadre de service Google, après quoi le système s'est écrasé. Un problème avec le magasin de clés est apparu (pas encore résolu). TEE est également temporairement désactivé, donc Widevine ne fonctionne pas. Les jouets et les applications fonctionnent correctement sans configuration matérielle particulière. Chrome tord la vidéo HTML5 avec un décodeur logiciel, refuse de brancher un décodeur matériel. A cette occasion, il y a une opinion sur l'AOSP déformé par les Chinois. Mais vanilla AOSP lance un lanceur avec un écran tactile - il est impossible de contrôler la distacha.

Postface


Dans un avenir proche - pour faire un lanceur pour lancer des applications Android directement à partir de Linux. Un exemple de ceci est disponible dans la source wpa-supplicant. Vous pouvez également voir comment cela se fait dans Anbox.

Merci de votre attention!

Addition 1


L'autre jour, j'ai vérifié l'évolutivité des applications Qt. Initialement, l'application client IPTV est écrite en QML pour Linux. Le lecteur fonctionne via le plugin QtMultimedia. Pendant la compilation, des dépendances problématiques sont apparues. Heureusement, tout était limité à QtDbus, qui n'est pas sous Android. Je ne comprends toujours pas pourquoi Android avait besoin de réinventer la reliure à roue. Qu'est-ce que les développeurs de DBus n'ont pas aimé? Que cela fonctionne dans l'espace utilisateur? Ou des considérations de licence?
DBus déconnecté. C'était indolore, car le canal était nécessaire pour un peu de fonctionnalités liées au système d'exploitation. Rassemblé apk. Il n'y a aucune difficulté avec l'assemblage, car j'utilise QtCreator (et je vous le recommande).
Dans AOSP, j'ai dû dessiner un pont Mediaplayer - un héritier d'Android :: MediaPlayerInterface. Les méthodes setDataSource () et stop () y ont été implémentées. Les prises sont faites pour le reste. setDataSource a trois interfaces. Il était nécessaire de mettre en œuvre uniquement:
 setDataSource(const sp<IMediaHTTPService> &httpService, const char *uri, const KeyedVector<String8, String8> *headers) 


Si vous voulez déformer des fichiers à partir de médias, vous devez bricoler avec
 setDataSource(int fd, int64_t offset, int64_t length) 

Le nom du fichier devra être obtenu via "/ proc / self / fd /" + fd;

Après l'installation, l'application a gagné et la diffusion est partie. Super! Je m'attendais à beaucoup de problèmes, mais il n'y en a presque pas. Merci aux développeurs de Qt et QtCreator pour le travail formidable et utile!
En conséquence, j'ai eu un tel groupe: le lecteur démon hôte. Dans le conteneur, il y a un programme client et une bande diffusant les appels d'Android :: Mediaplayer à l'hôte. Le bundle fonctionne via un socket UDP.

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


All Articles