Wie ein seltsames Bedürfnis entstand, Android in einem Linux-Container auszuführen, und was daraus wurde
Hintergrund
Das Ausführen von Android im LXC-Container ist meiner Meinung nach eine logische Entscheidung, wenn Sie die Transparenz und Zuverlässigkeit von Bare Linux nutzen und das enorme Potenzial guter (und nicht so guter) Android-Anwendungen von Drittanbietern nutzen möchten. Diese Konfiguration ist auch als Plattform zum Debuggen Ihres eigenen AOSP-Images unter Bedingungen nahe am Kampf von Interesse.
Für die Experimente wurde eine progressive und kostengünstige chinesische Set-Top-Box basierend auf 64-Bit-ARMv8 von Amlogic S905x ausgewählt (CPU - 4 Kerne, RAM - 2 GB, MMC - 8 GB). Ein gutes Argument (im Vergleich zu anderen Anbietern) war auch die Codebasis in OpenSource und das Vorhandensein des Quellkernel-Kerntreibers für Mali-450. Eine User-Space-Bibliothek Mali heute gemeinfrei auf der offiziellen Website von ARM Limited. Binärzugriffsbibliotheken für Linux-FB, Linux-Wayland und Android.
Der Hauptzweck der Experimente war die Anwendung von Online-Kinos und Anwendungen für die Arbeit mit Network Media Hosting. Zum Beispiel begannen mit Youtube unter Linux sofort Probleme. Erstens: Die Hacker-Methode zum Abrufen von Links zu Inhalten durch Parsen eines JS-Skripts und Generieren einer Signatur (zuvor in Minitube von Tordini und in youtube-dl implementiert) brach aufgrund des gnadenlosen Kampfes von Google mit Ad-Crawl-Methoden regelmäßig zusammen. Zweitens: Die maximale Auflösung des Inhalts betrug 720p - mehr Google-API wurde nicht ausgegeben. Drittens: WebKit hat die normale Unterstützung verloren und wurde kürzlich nur von einer kleinen Gruppe von Enthusiasten unterstützt. Das gleiche Schicksal ereilte seinen Qt-Hafen. Infolgedessen weigerte sich die Youtube / TV-Seite irgendwann, unter Berufung auf das Alter der Web-Engine zu funktionieren. Nun, am Ende brachte er eine überraschende WebEngine (Qt-Chromium) auf den Markt. Es stellt sich heraus, dass diese Schönheit die Hardwarebeschleunigung nicht unterstützt. Eine Ausnahme wird nur für den Android-Port und den marginalen VAAPI-Zweig unter Linux gemacht. Sackgasse. Im Allgemeinen habe ich keine einfache Möglichkeit gefunden, die hardwarebeschleunigte Videodecodierung für Chromium unter Linux zu aktivieren. Die Implementierung von VAAPI für Amlogic schien mir harte und nutzlose Arbeit zu sein. Ich habe auch das Pfeffer-Plugin gefühlt - PPAPI erlaubt leider keine Wiedergabe von Offscreen-Videos.
Android
Warum nicht Android in einem Container ausführen? Das Anbox-Projekt inspirierte das Kunststück. Eine gründliche Untersuchung von Anbox hat gezeigt, dass es nicht zu uns passt. Aber die Idee war klar. Artikel anderer Autoren behaupteten, dass das Ausführen von Android in einem Container eine dumme Aufgabe sei. Tatsächlich stellte sich jedoch heraus, dass alles viel komplizierter war. Durch einfaches Konfigurieren der Konfigurationsdateien konnten wir nicht aussteigen.
Also sammle ich LXC und installiere es im System. Der Kernel-Konfigurationstest zeigt Probleme auf: Sie müssen die Namespace-Unterstützung aktivieren. Da die Plattform integriert ist, wurden alle möglichen unnötigen Dinge deaktiviert. Ich musste diese notwendigen unnötig identifizieren.
Der erste Test war die Überprüfung der Busybox im Container. Nachdem ich sichergestellt hatte, dass alles funktioniert, begann ich zu experimentieren.
Die anfängliche Ansicht lautet /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
Laden Sie die Beute chinesische Hände AOSP 6.0.19. Es unterscheidet sich von der Vanille-Version durch das Vorhandensein eines normalen Launchers, der durch Distash und hart gepatchten Surfacelinger geschärft wird und einige Funktionen der Amlogic-Hardwareplattform unterstützt. Anschließend wurde auch Vanilla AOSP getestet.
Eine kleine Abweichung vom Thema: Die Chinesen, die die Software anpassen, spucken alle Regeln aus, die von der Community festgelegt wurden. Zum Beispiel der Kernel 3.14.29. Diese Silent-Kernel-Versionsnummer wird auf fast der gesamten Hardware von Amlogic S8xx- und S9xx-Prozessoren verwendet. Aber fast immer unterscheiden sie sich sehr stark voneinander, bis hin zur vollständigen Inkompatibilität alter Module mit neuen Bildern und umgekehrt. Es scheint, dass der Kern nach dem Prinzip korrigiert wurde: "So schnell wie möglich den Markteintritt des Produkts". Der Code ist nicht nur schmutzig - er ist von ekelhafter Qualität. Das Ändern der Konfiguration führt normalerweise zu Fehlern beim Kompilieren oder Verknüpfen des Images oder der Module. Gepatchtes Android hat die gleiche Qualität und die Prinzipien der Anpassung sind ähnlich. Fast alle Empfehlungen des AOSP-Teams werden ignoriert.Na nirgendwo hin! Wir sammeln.
Versuch Nr. 1 Installieren Sie das Image im Container und führen Sie es aus. Das ____ funktioniert nicht. Die Analyse zeigt, dass es keine Kernelobjekte gibt: Binder und Ashmem. Wir fügen Kernelmodule hinzu.
Versuch Nr. 2 Wir fangen wieder an. Installd stürzt ab. Es stellt sich heraus, dass der ursprüngliche Ordner keine Namespaces kennt. Ziehen Sie den Ordner aus Anbox.
Versuch Nummer 3 startet und geht sofort zum Neustart. Es stellt sich heraus, dass init SELinux will und sich weigert, ohne es zu arbeiten.
Versuch Nr. 4 Schalten Sie SELinux ein. Wir bekommen eine Reihe von Problemen für das Host-System. Zumindest für den Moment musste ich es ausschalten - bis das Wesentliche und die Theorie des Prozesses geklärt waren. SELinux kann auch in der Befehlszeile beim Laden des Kernels deaktiviert werden, aber ich verstehe immer noch nicht, wie Parameter an den Container übergeben werden. Ich musste in die Init-Quelle gelangen und ihr Verhalten grob korrigieren. Dies war der erste und letzte chirurgische Eingriff, der später auf mich zurückkam.
Versuch Nr. 5 Der Startvorgang erreichte die Zygote. In den Protokollen schwören vom Kernel auf die UID init. Im Ordner (und im Ordner von Anbox) kann die UID des Eigentümerprozesses leicht mit der Einheit verglichen werden. Die einzige Möglichkeit besteht darin, die Prüfung zu deaktivieren, zumal diese Prüfung im Container bedeutungslos ist.
Versuch Nr. 6 Konflikte im Zusammenhang mit der gemeinsamen Nutzung des Zugriffs auf die Geräteverwaltung sind aufgetreten. Ich kommentiere die USB- und Bluetooth-Steuerelemente in Init-Skripten. Ich entferne alle Einträge aus fstab und untersage das Mounten und Überprüfen aller Medien in Skripten. Fügen Sie nun die Mount-Karte zur Containerkonfiguration hinzu. Es enthält nur eine Zeile. Das Verzeichnis /mnt/lxc.data wird auf dem Host in einer echten MMC-Partition bereitgestellt.
lxc.mount.entry = /mnt/lxc.data data auto rw,bind 0 0
Versuch Nr. 7 Bouncing Balls erschien auf dem Bildschirm, der Download dauert lange, da das Android-Image auf NFS gemountet ist und Dexx auch im Verzeichnis / data generiert wird. Das Nachladen ist um ein Vielfaches schneller. Und schließlich erschien der Launcher.
Wir werden dies als den letzten Versuch betrachten, da im Allgemeinen alles funktioniert und Sie die Details fertigstellen müssen.
Das Netzwerk funktioniert nicht, es funktioniert genauer, aber einige Anwendungen bewerten seine Leistung anhand des Status der Netzwerkschnittstellen. Mit einem Wort krumme Hände. Um diesen Nachteil auf dem Host zu beseitigen, erhöhen wir die Netzwerkbrücke (Bridge) und die virtuelle Schnittstelle (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
Sie müssen auch den DHCP-Server hochfahren, da sonst Probleme mit DNS auftreten. Leider analysiert Android resolv.conf nicht und sein Speicherort im Dateisystem spielt keine Rolle. Sie können die Netzwerkverbindung manuell konfigurieren. Wenn Sie jedoch Daten aus dem Datenbereich löschen, werden alle Einstellungen zurückgesetzt.
Zusammenfassung
Alle Lageranwendungen funktionieren. Mit vom Markt installierten gibt es Probleme. Beispiel: Youtube.tv Version 3 forderte eine Aktualisierung des Google-Service-Frameworks, woraufhin das System abstürzte. Ein Problem mit dem Keystore ist aufgetreten (noch nicht behoben). TEE ist auch vorübergehend deaktiviert, sodass Widevine nicht funktioniert. Spielzeug und Apps funktionieren ohne spezielle Hardwareanforderungen einwandfrei. Chrome verdreht HTML5-Video mit einem Software-Decoder und weigert sich, einen Hardware-Decoder anzuschließen. Bei dieser Gelegenheit gibt es eine Meinung über die AOSP, die von den Chinesen schief heruntergespült wurde. Aber Vanilla AOSP startet einen Launcher mit einem Touchscreen - es ist unmöglich, die Distacha zu steuern.
Nachwort
In naher Zukunft - um einen Launcher zum Starten von Android-Anwendungen direkt unter Linux zu erstellen. Ein Beispiel hierfür finden Sie in der wpa-Supplicant-Quelle. Sie können auch einen Blick darauf werfen, wie dies in Anbox gemacht wird.
Vielen Dank für Ihre Aufmerksamkeit!
Zusatz 1
Neulich habe ich die Skalierbarkeit von Qt-Anwendungen überprüft. Zu Beginn ist die IPTV-Clientanwendung in QML für Linux geschrieben. Der Player arbeitet über das QtMultimedia-Plugin. Während der Kompilierung traten problematische Abhängigkeiten auf. Glücklicherweise war alles auf QtDbus beschränkt, das nicht in Android ist. Ich kann immer noch nicht verstehen, warum Android den Radbinder neu erfinden musste. Was haben DBus-Entwickler nicht gemocht? Dass es im User-Space funktioniert? Oder Überlegungen zur Lizenzierung?
DBus getrennt. Dies war schmerzlos, da der Kanal für einige Funktionen im Zusammenhang mit dem Betriebssystem benötigt wurde. Versammelte apk. Es gibt keine Schwierigkeiten mit der Montage, da ich QtCreator verwende (und ich empfehle es Ihnen).
In AOSP musste ich eine Mediaplayer-Brücke zeichnen - einen Erben von android :: MediaPlayerInterface. Darin wurden die Methoden setDataSource () und stop () implementiert. Für den Rest sind Stecker gemacht. setDataSource verfügt über drei Schnittstellen. Es musste nur Folgendes implementiert werden:
setDataSource(const sp<IMediaHTTPService> &httpService, const char *uri, const KeyedVector<String8, String8> *headers)
Wenn Sie Dateien von Medien verdrehen möchten, müssen Sie daran basteln
setDataSource(int fd, int64_t offset, int64_t length)
Der Dateiname muss über "/ proc / self / fd /" + fd abgerufen werden.Nach der Installation wurde die Anwendung verdient und die Übertragung ging. Großartig! Ich habe viele Probleme erwartet, aber es gibt fast keine. Vielen Dank an die Entwickler von Qt und QtCreator für die großartige und nützliche Arbeit!
Als Ergebnis bekam ich so einen Haufen: den Host-Daemon-Player. Im Container befinden sich ein Client-Programm und ein Strip, der Aufrufe von android :: Mediaplayer an den Host sendet. Das Bundle arbeitet über einen UDP-Socket.