Vom Android-NOOB zum Kernel-Entwickler und ROM-Portierer

  • 9 Antworten
  • Neuester Beitrag
Diskutiere Vom Android-NOOB zum Kernel-Entwickler und ROM-Portierer im Tipps und Anleitungen zum OS-Customizing im Bereich Android OS Entwicklung / Customize.
Kiwi++Soft

Kiwi++Soft

Ehrenmitglied
Da schon öfter Nachfragen kamen, wie man sich Wissen um Android OS-Entwicklung angeeignen kann, will ich es an dieser Stelle mal erzählen, in welchen Schritte das bei mir von statten ging. Ich möchte das in drei Hauptteile untergliedern. 'Wie habe ich Programmieren gelernt', 'Wie habe ich Android-OS gelernt' und 'Was ist die Botschaft'

Wie habe ich Programmieren gelernt:

Das Programmieren als solches habe ich als Kind gelernt, als ich den ersten Kontakt zu einem programmierbare Taschenrechner hatte (C64 gab es damals noch nicht). Das große Geheimnis an der Sache ist dabei das, dass alle Programmierbaren Systeme eigentlich auf dem gleichen Grundprinzip arbeiten. Es gibt nur sieben Grundwerkzeuge, die in allen Systemen gleich sind.

  1. Literale: Das sind in den Code fest einprogrammierte Werte, die unterschiedliche Datentypen wie Nummern, Text oder 'Logische Werte' (Wahr oder Falsch) haben können.
  2. Variablen: Einer Variable kann man einen Wert zuweisen, den man später wieder abrufen kann. Außerdem kann man der Variablen später auch einen anderen Wert zuweisen, und wenn danach die Variable abruft, erhält man den neu zugewiesenen Wert. Es gibt zwar die Sonderform der Variable, die man nicht ändern kann, aber das ist keine 'neue Qualität'. Man kann auch ohne dieses Werkzeug arbeiten.
  3. Operatoren: Operatoren verändern den Wert einer oder oder mehrer Literale oder Variableninhalte, so dass man das Ergebnis in einer Variable speichern kann, oder in einem anderen Zusammenhang (siehe unten) weiterverwenden kann.
  4. Bedingungen: Codepassagen können mit Bedingungen ausgestattet sein, dass die Codepassage nur dann ausgeführt wird, wenn die Bedingung erfüllt ist, ansonsten nicht. Im einfachsten fall ist die Bedingung ein Literal mit dem Wert Wahr oder Falsch, kann aber auch das Ergebnis eines Vergleichsoperators sein, oder der Inhalt einer Variable oder eine Kombination von diesen Möglichkeit. Der 'Else' Ausdruck ist hierbei keine neue Qualität, den er ist nur eine weitere Bedingung, ob die vorherige Bedingung nicht erfüllt war.
  5. Sprunganweisungen: Damit kann die Ausführung des Codes an eine andere Stelle des Codes umgeleitet werden. Mit Hilfe von Sprunganweisungen und Bedingungen können Schleifen realisiert werden. 'Nackte' Sprunganweisungen ohne 'Schleifenbedingungen' sind in modernen Programmiersprachen eher verpönt, da sie die Lesbarkeit des Codes beeinträchtigen.
  6. Funktionsaufrufe: Das sind im Prinzip auch Sprunganweisung, die aber zwei zusätzliche Qualitäten bieten und daher eine besondere Erwähnung verdienen. Funktionsaufrufen übergeben eine Rücksprung-Addresse um nach dem ausführen des Codes an die Stelle des Codes zurückkehren zu können, an der die Funktion aufgerufen wurde. Außerdem bieten Funktionen die Möglichkeit von Aufrufparametern und Rückgabewerten. Funktionen ohne Rückgabewerte werden bisweilen als Prozeduren bezeichnet. In der Objekt-Orientierten Programmierung spricht man auch gerne von Methoden, aber das ist nur eine besondere Form einer Funktion, die als Aufruf-Parameter einen Pointer auf ein Objekt beinhaltet, nur das das Objekt nicht in der klassischen Art als Funktions-Parameter notiert ist, sondern man Objekt.Methode schreibt, aber (auch wenn es mancher nicht glauben mag), das nichts anderes, als dass das Objekt an die Funktion übergeben wird.
  7. Pointer: Sind eine besondere Art von Variablen, mit deren Hilfe man Arrays und Strukturen (Und in der Objektorientierten Programmierung auch Objekte) aufbauen kann. Eine ganz besonders interessante Art der des Pointers ist der Funktions-Pointer, mit dessen Hilfe das Überschreiben von Methoden in erbenden Klassen in der Objektorientierung erreicht werden kann. Wenn in manchen Sprachen wie Java behauptet wir, man hätte keine Pointer, so dient das nur dazu dem Anwender die Angst vor dem Pointer zu nehmen, in Wirklichkeit ist jede Variable vom Type Objekt oder was davon erbt (inklusive des Types 'Array of Primitve') ein Pointer, nur nicht als solcher zu erkennen.

Wenn man sich diese Prinzips erst mal bewusst ist, wird einem klar, dass eine neue Programmiersprache zu erlernen ein 'Garnichts' ist.

Ich vergleiche es gern so:

Das Prinzip des Programmierens zu lernen, ist wie den Führerschein zu machen. Ob man den auf einem VW, Opel, BMW, Ford oder was auch immer macht, man lernt, wie das Auto bedient wird, welche Straßen es in der Heimatstadt gibt, aber vor allem, man lernt, wie man fährt. Letzteres ist das schwere.

Eine neue Programmiersprache zu erlernen, ist nichts anderes, als die Bedienung eines anderen Auto-Typs zu erlernen, wo ist der Lichtschalter, der Scheibenwischer und wie ist das Schaltschema? Mehr ist das nicht...

Eine neue Plattform (Win32-API, Standard-Java-Bibliothek, Android-SDK Java-Bibliothek) sich einzuarbeiten ist schon etwas mehr, das ist, um beim Auto-Beispiel zu bleiben, damit zu vergleichen, in eine neue Stadt zu kommen. Welche Straßen gibt es, in welcher Ecke der Stadt finde ich ein Einkaufszentrum, wo ist das Rathaus, wo kann ich parken?

Aber wenn man Autofahren kann, ist das eine lösbare Aufgabe.

Und das Programmieren als solches lernt man durch Übung. Klar ist, es gibt Techniken, die man mal erlernen muss, Rekursion beispielsweise, 'Was ist ein Eventloop, Techniken zum sicheren Einsatz von Multi-Threading usw. Aber auch das lernt man durch Übung. Mal ein Blick in ein Fachbuch oder Google ist nicht verkehrt. Aber Erfahrung kommt durch Übung....

Wie habe ich Android-OS gelernt:

Kernel-Entwicklung:

Ich denke ich kann mich was Android-OS angeht ganz klar als 'Späteinsteiger' bezeichnen. Mein erstes Android-Gerät (Acer A210 Tablet) bekam ich am 16.11.2012. Die ersten sechs Wochen habe ich mit kennenlernen und sinnloser Rumspielerei verdattelt, aber das wurde mir zu langweilig.

Also habe ich das Gerät gerootet und dabei die adb und fastboot Executables kennengelernt. Außerdem wurden mir die einzelnen Partitionen (Bootloader, Boot, System, Cache Data, Recovery) des Flash-Speichers bewusst. Ebenso wurde mir klar, dass im Boot-Image der Kernel und die Ramdisk drin liegen.

Nach dieser Erkenntnis wollte ich selbst mal einen Kernel builden. Also habe ich mal in Google 'Android Kernel builden' eingegeben und bin auf eine Anleitung gestossen, wie das gehen soll. In der Anleitung stand drin, dass man ein Linux-System braucht. Daher habe ich zuerst VirtualBox installiert und die ein Linux-System. Ich hatte zwar schon früher mal Kontakte zu Unix-artigen Systemen, aber eigentlich nur sehr rudimentär.

Nach der Installation des Lubuntu Linux konnte es dann mit der Kernel-Build Anleitung losgehen. Ich habe alle aufgelisteten Komponenten installiert, die Sourcen von Acer runtergeladen und wollte loslegen. Der erste Build ging jedoch in die Hose. Also habe ich erste Fehlermeldung in Google eingegeben und nach ein paar Trefferseiten fand ich heraus, dass man in einem 64-Bit Linux ein paar 32-Bit kompatiblitäts-Pakages installieren muss, dass der Crosscompiler funktioniert. Ein paar kleinere Probleme später lief mein erster Kernel Build durch.

Dank Google fand ich dann auch eine Anleitung, wie man aus einem Kernel ein Boot-Image baut. Danach hat mein Tablet das erste mal mit einem von von mir gebauten Kernel gebootet. Also bin ich mal die Liste der der in den Sourcen enthaltenen Treiber und Module durchgegangen, und habe das CIFS-Modul gefunden (um auf Windows-Shares zuzugreifen) gefunden, das erste Modul das nicht im Stock-Kernel eingebaut war, das ich nutzen konnte, da ich im Heim-Netzwerk einen kleinen Fileserver habe. Kernel gebaut, Mount Befehl gegooglet und schon konnte ich ein Netwerk-Laufwerk richtig mounten (und musste nicht mehr so einen SMB-Streaming-Client wie ES-Datei-Explorer nutzen).

Da ich diesen Kernel hier im Forum gepostet habe (falls andere User auch Netzwerklaufwerk mounten wollten) wurde ich irgendwann gebeten, einen OC-Kernel zu bauen. Da das Einbinden von Module, die ohnehin schon im Source-Tree drin sind ohnehin langweilig war, erschien mir das eine spannendere Aufgabe und ich habe angefangen, mich in die Kernelsourcen einzulesen. Als ersten Schritt habe ich das grep --help eingegeben, um zu lernen, wie ich die Sourcen durchsuchen kann. Mit 'grep -r 1300 ./' habe ich schnell die Datei gefunden, in der die Takt und Spannungs-Werte für den Kernel gesetzt werden. Nach etwas Code-Studium habe ich auch das Prinzip erkannt, wie der Tegra3 Kernel den Takt regelt und konnte meinen ersten OC-Kernel bauen.

Damit hat mein Kernel-Projekt begonnen. Der nächste Schritt war dann, dem Kernel einen Kommandozeilen Parameter mitzugeben, ob er mit oder ohne OC arbeiten soll, um nicht zwei Source-Trees für mit und ohne OC pflegen zu müssen. Auch diese Info habe ich mit 'Linux Kernel Commandline' über Google gefunden.

Der nächste grosse Erkenntnis-Schub kam dadurch, dass ich zur Laufzeit das OC aktivieren oder deaktivieren wollte. Dazu musste ich einerseits ein Binary dass man über das Android-Terminal aufrufen kann entwickieln, andererseits die Kommunikation zwischen Binary und Kernel erlernen. Wieder war Google mein Freund, und ich habe gelernt, wie man das Android-NDK (Native Development Kit) verwendet.arbeiten wollte

Da die User nicht mit einem Kommadozeilen Tool arbeiten wollten, musste ich auch meine erste Android-App schreiben, um eine Benutzer-Freundliche Oberfläche anzubieten. Dazu habe ich mir Eclipse und Android-SDK installiert und die mitgelieferte Doku gelesen.

Ein weiteres sehr lehrreiches Stück Code war der Schritt, in meinen Kernel eine 'Multiuser' Fähigkeit einzubauen, was aber in Wirklichkeit nicht im Kernel stattfindet. Ich biete an, dass man die externe SD-Karte in eine oder mehrere Ext-4 Partitionen formatiert, die dann beim Booten als 'Data' Partition anstelle der internen Data-Partition im internen Flash-Speicher verwendet wird. Somit hat man verschiedene Data-Partitionen, die jeweils einen eigenen Stand an Apps und Konfiguration darstellen, wie eben verschiedene User in Windows das täten. Allerdings musste ich dazu eine Auswahlmöglichkeit, welche Partition genutzt werden soll, dem User anbieten, bevor das Android-System gestartet wird. Ein Beispiel wie sowas geht ist das CWM-Recovery, das auch eine Benutzer-Oberfläche anbietet, ohne dass Android läuft. Nach kurzem Codestudium kam ich auf die Nutzung der Android-Bibliothek libpixelflinger.so zur Darstellung meiner Oberfläche. Das Abgreifen von Touch-Events habe ich wieder über Google gelernt.

ROM-Porting:

Eigentlich hatte ich nicht beabsichtigt, mich mit ROM-Porting zu beschäftigen. Mein primäres Ziel war, meinen Boot-Selektor als 'StandAllone' Executable bauen zu können, der nicht auf die Anwesenheit der libc.so und der libpixelflinger.so angewiesen ist. Dies ist jedoch mit dem Android-NDK nicht möglich, da dieses keine 'static libraries' anbietet. Da aber CWM ein 'StandAllone' Executable ist, wurde mir klar, dass in dem Build-Prozess für ein CyanogenMOD auch 'static libraries' aus libc und libpixelflinger gebaut werden. Also habe ich mir die Anleitungen, wie man AOSP und CM baut durchgelesen und ein entsprechendes Build-Environemt aufgesetzt.

Inzwischen wurden im A210 Forum die Rufe nach Android 4.2.2 immer lauter, und da ich das Build-Environment schon hatte, habe ich angefangen, ein CM für das A210 zu erstellen. Der erste Schritt ging sehr leicht, da ich die 'Gerätespezifischen Treiber' von einem anderen Acer Tablet kopieren konnte, und mit meinem Kernel kombinieren konnte. Zum Glück gingen der Display- und Touchscreen Treiber sofort, so dass ich erst mal ein 'bedingt lauffähiges' System hatte. Wifi, Audio-Treiber, Kamera und Bluetooth haben aber viel Code-Studium, Googlen und Fehlversuche gebraucht, bis auch diese nach 4 Wochen soweit stabil liefen, dass ich 'vollständigen Hardwaresupport' proklamieren konnte.

Einen letzen Bug zu fixen war die Entwicklung eines speziellen vold Executables, dass den UFSD Kerneltreiber des A210 für NTFS-Laufwerke unterstützt. Auch hier waren wieder Google und viel Testen mit von der Partie.

Was ist jetzt die Botschaft dieses langen Textes:

Entwicklung und Plattform-Know-How lernt man nicht von heute auf morgen. Man lernt es auch nicht bevor man anfängt, etwas zu tun.

Man überlegt sich, was man tun möchte, und wenn sich eine Wissenslücke auftut, sucht man sich die benötigten Informationen.

Wie stopft man eine Wissenslücke:

Der schnellste Weg ist nicht der, jemanden zu fragen. Ich frage nur als letzten Ausweg, denn ich habe nicht die Geduld, auf eine Antwort zu warten.

Mein erster Versuch ist die Doku. Wie schon Meister Yoda zu sagen pflegt: 'RTFM, you must'!

Ist in der Doku (oder --help oder Man-Pages) nichts zu finden, versuche ich es mit Google. Oft habe ich das Glück, über Google eine passende Antwort zu finden. (Man entwickelt im Laufe der Zeit auch ein Gespür dafür, welche der Treffer von Google einem bei welchem Thema weiterhelfen.)

Wenn da auch nichts zu finden ist, kann man sich überlegen, in welchem Open-Source-Projekt ähnliche Probleme gelöst wurden. Dann kann man im Source-Code nachgucken, wie es dort gelöst wurde.

Erst wenn das alles nichts hilft, stelle ich mal eine Frage im Forum. (Hier meinen besonderen Dank an Perpe, die mir freundlicherweise so manches Mal geholfen hat!). Jetzt gibt es wieder zwei Möglichkeiten. Entweder man bekommt direkt eine Antwort, die das Problem löst, oder man bekommt eine 'Denkanregung', so dass man aus der Sackgasse, in der man sich verbohrt hat, herauskommt und mit frischen Ideen weitermachen kann.

Fantasie ist alles:

Wenn ich partout keine Informationen bekomme, wie ich eine bestimmte Sache machen kann, hatte ich schon oft Erfolge damit, mir zu überlegen was ich alternativ tun kann, um den gleichen Effekt zu erreichen.

Bevor es mir gelungen ist, mit einem android-Executable mit meinem Kernel zu kommunizieren, hatte ich eine alternative Lösung verwendet (die zwar nicht so elegant war, aber ich hatte aus nicht näher benannten Gründen Zeitdruck), die auch funktioniert hat. Also habe ich nachladbares Kernel-Modul geschrieben. Kernel-Module können beim Laden Parameter übergeben bekommen. Auf diese Weise konnte man dem Kernel zur Laufzeit ebenso Parameter übergeben.

Nachdem ich die Lösung hatte, konnte ich mich in Ruhe damit beschäftigen, wie es 'richtig' zu machen ist.

Manchmal hilft ein bisschen Phantasie, ein unlösbare Problem einfach zu umschiffen.

Ich hoffe, damit andere User ermutigen zu können, den gleichen Weg zu gehen. Und vielleicht haben andere User ja auch Lust, mal zu berichten, wie sie zu Ihren Kenntnissen und Fähigkeiten kamen. Dann könnte das eine ganz hilfreiche Sammlung werden.

Grüsse Uwe
 
Zuletzt bearbeitet:
Oebbler

Oebbler

Erfahrenes Mitglied
Hallo,

danke für deinen Text! Bei mir hat es fast genauso angefangen wie bei dir. Ich habe mir mein erstes Android-Gerät im Juli 2012 gekauft(es war das Samsung Galaxy 5)und mich erst einmal mit dem Gerät und mit Android vertraut gemacht. Nach wenigen Tagen habe ich im Einstellungsmenü alles Mögliche und Unmögliche gemacht und bin auf Fehler im System gestoßen. Das hat mich neugierig gemacht. Ich habe dann einiges über Android im Internet gelesen und bin sehr oft auf den Hinweis gestoßen, dass das eine oder andere Root-Rechte erfordert. Dann habe ich mich informiert, was man zum Rooten braucht, nämlich eine su-Binary und die dazugehörige Superuser-App. Das habe ich heruntergeladen und dann adb installiert. Anschließend habe ich mich mit den Befehlen von adb vertraut gemacht und dann durch Ausprobieren die Systempartition gehackt(normalerweise hat man da nur Leserechte)und dann die su-Binary eingefügt. Die Superuser-App musste ich separat installieren, da das Gerät die Schreibrechte wieder entfernt hat, was dann aber egal war. Ich habe mir viele Root-Apps angesehen und das System verändert. Dabei ist das Smartphone sehr oft kaputtgegangen, ich habe es aber jedes Mal selber repariert. Dadurch habe ich viel dazugelernt. Irgendwann bin ich über einige Internetseiten gestolpert, auf denen erklärt wird, wie man Custom-ROMs flasht. Das hat mich dann auch interessiert, sodass ich mir CyanogenMod 10 heruntergeladen habe. Damals habe ich aber noch nicht gewusst, dass Custom-ROMs nur mit einer Open Recovery Script-fähigen Recovery, wie z.B. Clockworkmod lauffähig sind. Auf diese Art und Weise bin ich immer mehr in die Untiefen des Android-Systems vorgedrungen. Ich habe immer größere Schwierigkeiten bekommen, jemanden zu finden, der die Antwort auf meine Fragen hat, da sich mein Wissen schnell erweitert hat. Mittlerweile schreibe ich sogar eigene Custom ROMs, wie in der Signatur zu lesen ist. Demnächst wird auch ein Custom-Rom mit selbst gemachtem Kernel für das Nexus 7(2012) erscheinen. Wie lange das dauert, kann ich im Moment nicht sagen.

Die Enwicklung von Android ist alles andere als langweilig. Wer das angehen möchte, dem sei gesagt: "Es ist viel einfacher als man denkt. Das Erlernen einer Programmiersprache ist das Schwierigste daran."
Ich würde mich freuen, wenn ihr eure Erfahrungen damit auch teilen würdet.
 
H

hamza189

Neues Mitglied
Vielen Dank für diese wird mir helfen, so viel in meinem Lernen. Ich habe dies merkt und wird bald wieder mehr zu danke.
 
C

Croal

Neues Mitglied
Hi Leute,
Ich versuche auch Programmieren zu lernen dabei habe ich den Weg über einen Roboter Bausatz Pro-Bot 128 zu bauen und selbst zu Programmieren. Auf dem weg bin ich auf das Cubieboard 2 gestossen wo Android 4.2.2 drauf ist. Ich muss sagen das ich mit der Zeit ein Android Fan geworden bin und anders als die meisten Cubieboard nutzer, statt linux zu installieren viel lieber weiterhin Android nutzen würde. Auf der suche nach eine aktuellere Android bin ich auf diese seite gestossen. Nun meine kenntnisse in sachen Programmieren sind sehr beschränkt aber mich würde interresieren wie ich zB. Android 4.4 auf das Cubieboard bekommen könnte, was würde passieren wenn ich einfach 4.4 drauf flashe?
Sind die Treiber vorhanden oder wie man die nachinstalliert? Könnte mir jemand ansatzweise erklären welche schritte nötig sind um mich damit auseinander zu setzen?
Ein Angepasstes 4.4 wäre sehr geil aber ich denke das wär ein bisschen viel verlangt.
Danke Croal
 
Zuletzt bearbeitet:
C

Croal

Neues Mitglied
Ach cool danke für den link. Ich werd mich damit ausseinander setzen um etwas dazu zu lernen. Noch eine Frage, was würde passieren wenn ich Android einfach über das Cubieboard Flashe, das Board hat ein A20 cortex a7 und ein dualcore mali 400 Gpu . Biringt 4.4 die Treiber mit, müssen die noch geschrieben werden extra für 4.4 oder wäre möglich die Treiber von 4.2.2 zu nehmen was zur zeit drauf ist?
Danke Croal
 
Kiwi++Soft

Kiwi++Soft

Ehrenmitglied
Ein Android ist immer für ein bestimmtes Gerät. Ein Android für ein anderes Gerät drüber zu flashen wird in den meisten Fälle (außer die Geräte wären extrem ähnlich) zu einem nicht startenden Gerät führen.

Was die Treiber angeht, ist folgendes zu beachten: Ein großer Teil der Treiber ist schon im Kernel. Der muss an die Android-Version angepasst sein. Die restlichen Treiber (Vendor-BLOBs genannt) sind im ROM, die Treiber von Android 4.2 sind nur zum Teil mit Android 4.4 kompatibel, da muss man teilweise Wrapper basteln oder anderweitig kreativ sein...

Dazu kann man auch nichts pauschal sagen, denn das ist hochgradig Geräte abhängig. Das macht eben gerade die Arbeit eines Device-Maintainers (Das ist derjenige, der den Device-Tree für ein bestimmtes Gerät erstellt) aus.

MfG Uwe
 
Zuletzt bearbeitet:
C

Croal

Neues Mitglied
Ok danke jetzt bin ich total verunsichert. Ich glaube oder bessergesagt weiss das ich das nicht packe.
 
Zuletzt bearbeitet von einem Moderator:
H

hamza189

Neues Mitglied
hamza189 schrieb:
Vielen Dank für diese wird mir helfen, so viel in meinem Lernen. Ich habe dies merkt und wird bald wieder mehr zu danke.


______________________________
 
Zuletzt bearbeitet:
Jaiel

Jaiel

Experte
Hallo ich interressiere mich auch sehr für betriebssysteme...mal ne anfänger frage:

Du hast jetzt aber nciht einen ganzen Kernel vom scratch aus aufgezogen sondern "nur" die Libraries aussen rum oder?

Wie ist denn das bei Android eig so ... ich lese mcih grad in die linux architektur ein...warum müssen Androids für jedes Gerät neu entwickelt werden? Liegt das an den Herstellern und deren Hardware? Der Android Kerneöl an sich kann ja überall verwendet werden und es sind wirklich nur die libraries...für Treiber , die GUI(oder ist die auch im kernel enthalten) etc. anzupassen wenn ich das richtig verstanden habe