HowTo: Android in der Linux KVM

[nggallery id=5]

Vorwort:

[update: dieses HowTo ist alt. Derzeit habe ich kein passendes Image mehr zum Download]

Dieses kleine HowTo richtet sich prinzipiell an Jeden, der einfach mal auf einem PC mit Android rumspielen will, aber selbst nicht die Zeit und Motivation aufgebracht hat, es selbst zum laufen zu bringen. Gründe dies zu tun wären z.B. wenn man selbst kein Andoid Gerät hat, oder nur ein veraltetes, so wie ich und mal sehen möchte, was denn im Lager Google gerade der Stand ist. Auch für Entwickler ist ein Virtuelles System natürlich interessant, weil man bei Experimenten nichts beschädigen kann, was man gleichzeitig im täglichen Gebrauch hat.

Eigeninitiative ist kaum noch nötig, es wird ein Archiv verwendet, in dem ein fertig installiertes Image liegt und ein Shell Skript, welches die KVM mit den nötigen (und richtigen) Optionen startet.

Nachtrag: Obwohl nicht mehr sonderlich viel zu tun ist, gelang es mir nicht, mich kürzer zu fassen, ohne dabei diejenigen zu vernachlässigen, die ggf. etwas mehr Hilfe brauchen.

Warnung / Hinweis:

Dieses HowTo ist wirklich nur für die Linux KVM. Die verwendeten Befehle machen nur unter Linux Sinn und das verwendete Image hat absichtlich keinen Bootblock, da die KVM den Android Kernel selbst bootet.

Warum?

Ich teile hier meinen eigenen Wissensstand, einfach nur weil ich Spaß daran habe und diesen mit Anderen teilen will. Die Worte Windows, VMWare und Spaß kann ich mir nicht in einem positiven Zusammenhang vorstellen, ohne dass nicht mindestens eins davon negiert ist.
Selbstverständlich kann man Android auch virtualisiert unter Windows zum laufen bekommen, aber das interessiert mich nicht und ich werde mich nicht in meiner Freizeit damit beschäftigen.

Motivation:

Möglichkeiten der Virtualisierung gibt es sicher viele und wie es immer so ist, wenn man keine fertige Monokultur vorgesetzt bekommt, sollte man sich zunächst informieren, denn es gibt ebenso viele Möglichkeiten, etwas, sagen wir mal, weniger gut zu lösen.

Weniger gut ist imho die Lösung die Google selbst. Wer den hauseigenen Emulator nutzen will, kommt nicht darum, das Ganze SDK aufzuspielen, eine Zielplattform auszuwählen und diese auch noch zu konfigurieren. Schritte, die für Jemanden, der eher Nutzer als Entwickler ist, alles andere als trivial sind.
Auch die Art, wie Google den Emulator implementiert hat, ist … ungewöhnlich. Normalerweise werden Emulatoren so systemnah wie möglich entwickelt, da sie, als Herzstück der Virtualisierung, entscheidend für die Performanz des Gastsystems sind.
Google schien die Portabilität des Emulators wichtiger zu sein - sie verwendeten Java. Mehr müsste man eigentlich nicht sagen. Ich fasse dennoch zusammen:
Ein Emulator, der in Java geschrieben ist, emuliert ARM Hardware, auf der Java läuft.
WTF!!!
Zumindest auf meiner bescheidenden Hardware ist das Konzept unbenutzbar und produziert auch nach mehreren Minuten nur eine Menge warme Luft aus dem Gehäuse, bevor dann endlich eine elendig lahme Oberfläche kommt.

Ansatz:

Auf meiner Suche nach einer brauchbaren Alternative, stieß ich auf das Projekt
Android x86. Deren primäres Ziel ist es zwar, Android auf physikalisch existierende PC Hardware zu bringen, aber schließlich ist es auch primäres Ziel einer guten Virtualisierung, physikalisch existierende Hardware möglichst nah und performant abzubilden.
Tatsächlich finden sich auch einige, leider zu kurze und veraltete, Tutorials für die Virtual Box. Warum sie gerade die verwenden, wird nirgendwo erwähnt, aber ich gedenke ja auch nicht, mich für die Präferenz der KVM zu rechtfertigen.
Also Android auf einer x86 KVM. Nun kommt natürlich die Frage:

Andoid auf x86? Ist das nicht für ARM entwickelt? Funktioniert das?

Zumindest die letzte Frage kann ich direkt und präzise mit Ja *beantworten. Wäre dem nicht so, würde ich dazu kein HowTo schreiben. Bei der zweiten Frage, wird es schon schwieriger.
Generell wurde Android für die Dalvik VM entwickelt. Diese ist im Gegensatz zu z.B. der OpenJRE eine Stack orientierte Maschine und keine Registermaschine. - Hä? - Irrelevanzinformation.
Soll heißen: Das meiste von und für Android sollte Plattformunabhängig sein.
*
Sollte
.
Wäre dem 100%ig so, würde Google kein NDK (native development kit) bereitstellen. Zunächst ist natürlich ohnehin Alles erst mal bis zum Start der Dalvik VM native Linux. Das kann man in jeder brauchbaren Umgebung, für nahezu jede weiter verbreitete Hardware, kompilieren und so hat es das Android x86 dann auch gemacht.
Effektiv scheitern werden wir bei einigen Paketen also nicht an der Hardware, sondern am Paketmanagement von Android selbst. Dieses kennt nur komplette Zielgeräte und die Kompatibilitäten dazu einzustellen, ist den Entwicklern überlassen. So kommt es, dass es Pakete gibt, die angeblich überall funktionieren, dann aber doch ein paar entscheidende Brocken native ARM Code enthalten, der dann wortlos einfach nicht funktioniert.
Bei meinen ersten Versuchen, war das noch ein ärgerliches Problem. Die von mir jetzt eingesetzte Version enthält ein paar Librarys von Intel, die notfalls einspringen und den ARM Code, meist erfolgreich, laufen lassen. Wir erinnern uns: Es gibt jetzt auch Android Tablets mit Intel Atom Prozessoren.
Des Weiteren ist noch ein Ethernet Patch dabei, der für die nötige Unterstützung des Netzwerkinterfaces sorgt.
Leider ist die Dokumentation von Android x86 etwas veraltet, was die Virtualisierung angeht - fertige Images gibt es entweder undokumentiert generisch, oder ebenso undokumentiert für diverse Laptops. Welche Hardware die KVM nun verwenden soll, ist daher ein langweiliges ausprobieren, welches ich euch gerne ersparen würde. Die Virtuelle Soundkarte, welche funktioniert, hat zwischen den beiden Images, die ich jetzt verwendet habe, gewechselt und in beiden Fällen war es nicht die, die im Virtual Box HowTo des Projekts empfohlen wird.

Ja, Ja - Los jetzt! - Setup:

Benötigt wird:

  • Die KVM
  • Dieses Archiv mit dem Image
  • XZ um es zu entpacken (entschuldigt die Bandbreite schonende Unannehmlichkeit)
  • ein echtes Netzwerkkabel (am Netz, bitte)
  • eine virtuelle Ethernet Bridge
  • das Usermode Ethernet Interface tap0 für die KVM
  • das Paketmanagement deiner Wahl um evtl. hiervon fehlende Pakete zu installieren
    Die Anweisungen zur Paketinstallation beziehen sich im Folgenden auf Ubuntu. Die Pakete sollte aber auch auf anderen gängigen Distributionen verfügbar sein. Falls der Paketname nicht stimmt, nicht gleich entmutigen lassen, sondern einfach nach dem Befehl suchen.
    Ich verwende den simplen Befehl apt-get. Selbstverständlich kommt man auch mit aptitude und synapticzum Ziel. Anfängern empfehle ich synaptic. Das ist übersichtlich und grafisch, arbeitet aber langsamer, da es unter der Haube so einiges werkeln muss, um diesen Luxus zur Verfügung zu stellen.
    Für Distributionen die nicht von Debian abstammen, fallen mir noch emerge und yast ein, Letztes kenne ich nur noch rudimentär, Ersteres gar nicht. Normalerweise sollte ein grafischer Desktop irgendwo eine Paketverwaltung anbieten. Genug dazu.

KVM:

Die KVM sollte installiert sein. Wer noch nie damit gearbeitet hat, muss sich nicht fürchten, ein passendes Startskript ist dabei. Falls die KVM noch nicht installiert ist hilft hier:

sudo apt-get install kvm

das wars dazu auch schon.

Image:

Spätestens jetzt ist es an der Zeit, das Archiv zu laden. Bitte irgendwo speichern, wo Du es nachher wieder findest. Downloads ist nur eine beschränkt gute Idee, da das folgende Kommando es genau dort hin extrahieren wird.
Die ISO zur Installation habe ich übrigens von www.android-x86.info geladen. Die Installation habe ich Euch soweit erspart und bis zum ersten Boot selbst vorgenommen. In den Bootoptionen der KVM wird eine zweite Partition für eine SD-Karte übergeben. Einige Apps hätten gerne eine Solche.
Der Installer von Android x86 stellt sich dabei aber gerne quer, oder will unbedingt ein Fileimage dafür anlegen. Ein Fileimage in einem Fileimage ist schon fast ein bisschen wie Java auf ARM, dass von Java emuliert wird.
Ich würde gerne den Author der ISO, Ron M. dafür verlinken, finde ihn aber nicht.

Auspacken:

XZ ist der Nachfolger von LZMA, oder kurz, der meines Wissens nach der effizienteste momentan in der Open Source Welt verfügbare Packer. Er darf auch gerne nach dem Extrahieren wieder entfernt werden.
Falls du kein XZ hast:

sudo apt-get install xz-utils

Wenn Dein distributionseigenes tar xz unterstützung hat, reicht nun ein:

tar xvJf <Pfad zum Archiv>

ansonsten

xzcat <Pfad zum Archiv> | tar xv

Das Netzwerk:

Hier gab es jetzt zwei Möglichkeiten. Die KVM kann sich von Haus aus so verhalten, als wäre das Gastsystem in einen Router eingestöpselt.
Ich habe mich gegen diese Möglichkeit entschieden, weil damit Andoid in einem virtuellen Netzwerk eingesperrt wäre, aus dem es zwar raus kommt, weil die KVM die Internen IP Adressen übersetzt und weiterleitet - wie ein Router ins Internet weiterleitet (NAT) - aber man kommt aus dem lokalen Netz nicht rein. Mit meinem Setup erhält Android eine eigene IP Adresse aus dem selben Netz, welches auch der Host Rechner verwendet. Das ist für Debugging, Entwicklung und eigentlich überhaupt prinzipiell so ziemlich Alles besser.
Der Haken:
Das funktioniert nicht mit WLAN. Es sei denn man verwendet einen Router welcher WDS unterstützt und dafür richtig konfiguriert ist (was nur komische Leute wie ich machen). Dann müsste man die virtuelle Bridge und das WLAN Interface des Host Rechners (wenn es überhaupt WDS kann) aber auch noch dafür konfigurieren.
Muss nicht sein, oder?
Ohne WDS wird jedenfalls kein Paket vom WLAN-Router das Gastsystem erreichen, weil dieser immer direkt an den Zielrechner Adressiert. Die WLAN Schnittstelle gehört aber dem Host.
Nimmt man stattdessen ein Kabel, kommen Pakete für den Gast über die Bridge auch direkt ohne Umwege beim Gast an.
Da wir uns jetzt für ein Kabel entschieden haben, können wir ja weiter machen.

Die Bridge:

Die Ethernetbridge ist nun keine besondere Zauberei, sondern genau das, was heutzutage in so ziemlich jedem Router die Pakete zwischen Kabel und Kabellos verteilt. Sie verbindet physikalisch getrennte Netzwerke miteinander, indem sie auf allen Anschlüssen lauscht wer redet und dann ggf. Pakete von einer Seite auf die andere weiterreicht, wenn die Parteien hinter verschiedenen Netzwerkschnittstellen sind.
Ob dies nun wirkliche Netzwerke sind, oder nur ein virtuelles, wie bei der KVM, ist der Bridge dabei egal. Wie praktisch.

Wer die Ethernet Bridge nicht installiert hat, holt das mal eben schnell nach:

sudo apt-get install bridge-utils

Der Einfachheit halber erstellen wir auch gleich ein Interface und fahren es hoch.

sudo brctl addbr br0
sudo ip li se up br0

Den Syntax des ip Befehls lässt sich in der Regel auf zwei Buchstaben verkürzen und ist daher etwas gewöhnungsbedürftig. In älteren Distributionen gehört er noch nicht zur Standardausrüstung. Alternativ kann ifconfig verwendet werden.

ifconfig br0 up

Das ist in diesem Fall sogar kürzer, der Befehl ist aber nicht so universell einsetzbar und wird von mir daher nur noch selten verwendet. Falls Du ip nicht hast, kannst du jedes Auftreten mit ifconfig ersetzen. Für etwas Anderes, als zum Hochfahren von Interfaces, werden die Befehle in diesem HowTo nicht gebraucht.

Das TAP Interface:

Dieser Abschnitt könnte mehr oder weniger überflüssig sein, denn die KVM kann selbst ein TAP Interface richtig konfigurieren und verwenden. Das kann sie aber nur, wenn sie die nötigen Rechte dazu hat d.h. die KVM die ganze Zeit als ROOT läuft.
Da wir der KVM aber nur so viele Rechte wie eben nötig geben wollen, stellen wir dieses Interface selbst bereit. Dazu brauchen wir die uml-utilities.

 sudo apt-get install uml-utilities

Genauer gesagt, den Befehl tunctl.

sudo tunctl -u <dein Username>

Das System sollte Dir jetzt bestätigen, dass es das Interface tap0 für Dich angelegt hat. Das Besondere daran ist, dass es nun auch mit deinen Nutzerrechten verwaltet werden kann. Solltest du nicht tap0 bekommen haben, existiert es vermutlich schon, weil du selbst Etwas damit machst und ohnehin genau weist was du tust.
In dem Fall brauchst Du diesen Abschnitt wohl nicht. Vergiss dabei bitte nicht, dass ich davon ausgehe, dass wir mit tap0 arbeiten.
Das Hochfahren auch nicht vergessen.

sudo ip li se up tap0

Die Netzwerkkonfiguration:
Nun wird es etwas kniffeliger. Bis jetzt haben wir mit Netzwerkschnittstellen rumgefummelt, die der automatischen Netzwerkverwaltung relativ egal sind, solange Niemand etwas für sie angelegt hat. Das ändert sich nun.
Daher muss jegliche automatische Netzwerkverwaltung abgeschaltet werden. Dies kann und wird Deine Internetverbindung trennen, wenn auch nur temporär.

sudo stop network-manager

Dieser Befehl könnte unter Umständen sehr ubuntuspezifisch sein. Alternativen kann ich für andere Distributionen leider nicht anbieten, da ich nicht weis, wie die ihr Netzwerk konfigurieren.
Auch die Netzwerkschnittstelle eth0, mit der ich die KVM verwenden will, wurde hierdurch dekonfiguriert und heruntergefahren. Also muss sie zunächst wieder hochgefahren werden. Wenn Deine primäre Netzwerkschnittstelle für Kabel Ethernet nicht eth0 ist, gehe ich wieder mal davon aus, dass Du die erforderlichen Änderungen selbst nachvollziehen kannst.

sudo ip li se up eth0

Die Schnittstellen müssen nun genau in dieser Reihenfolge in die Bridge integriert werden, denn die Ethernetadresse der Bridge wird sich in den meisten Fällen nach dem Interface richten, welches als Erstes hinzugefügt wurde.

sudo brctl addif br0 eth0
sudo brctl addif br0 tap0

Das würde jetzt für die KVM ausreichen, um sich ins Netz zu integrieren, nur wäre es ja auch ganz schön, wenn das Host System auch wieder Netz hätte. Dazu fehlt nur noch eine IP Adresse. Wir benutzen jetzt aber nicht mehr die Netzwerkschnittstelle direkt, sondern die Bridge.

sudo dhclient -v br0

Dabei gehe ich natürlich davon aus, dass das Netz DHCP verwendet. Wenn das nicht der Fall ist, sollte Derjenige, der das abgeschaltet hat, auch wissen, was zu tun ist.

Der erste Start:

Hierfür reicht es, kvmstart.sh im Verzeichnis auszuführen, wo das Archiv extrahiert wurde.

. kvmstart.sh

Ja, richtig gesehen. Das beginnt mit einem Punkt. Alternativ wäre auch source möglich gewesen. Ich wollte nur vermeiden, für eine Zeile eine Shell in der Shell auszuführen, die die KVM ausführt. Muss ja nicht sein.
Das wäre es dann auch endlich von meiner Seite aus. Die KVM sollte starten und Android wird Dich nach Deinem Google Account usw. fragen. Vorher muss noch eben bestätigt werden, dass der Wizard für die Systemanmeldung verwendet werden soll. Durch die Anmeldung kann die KVM wie ein reguläres Android Device verwendet werden. Pakete können also bequem über den Play Store installiert werden, der allerdings bis zum ersten Update noch Google Market ist.

Hinweis:

Die KVM wird den Mauszeiger einfangen, da diese einfache Version der Konfiguration eine Maus emuliert. Den sog. Mausgrab verlässt man mit Strg + Alt.
Wer davon genervt ist, kann durch das Anfügen der Optionen -usb -usbdevice tablet an die KVM Kommandozeile in kvmstart.sh auf ein virtuelles usb Tablet wechseln. Die Maus verlässt dann das Fenster, sobald sie am Bildschirmrand ankommt.
Abschließend sei erwähnt, dass die Grafik geringfügig beschleunigt werden kann, wenn man die KVM stattdessen mit VNC Display Ausgabe arbeiten lässt. Dann braucht man natürlich auch ein VNC Viewer um die Anzeige sehen zu können. Mehr dazu, falls jemand danach fragt.