====== Entwickeln & Bauen für die Head-Unit ====== Wie du einen Rechner einrichtest, um Apps für die Aiways-U5-Head-Unit (Adayo i.MX6, Android 4.4.2) zu bauen, zu signieren, zu installieren und zu debuggen. Siehe [[de:hardware|Hardware & Betriebssystem]] für die Plattform und [[de:access|So kommst du rein]] für den Zugang. ===== Beispiele ===== Vier kleine Apps, die du im Auto installieren kannst — gute Einstiegspunkte, die zeigen, wie die Teile zusammenspielen. Jede läuft als System (''sharedUserId="android.uid.system"'') und ist mit dem Platform-Key signiert. ^ App ^ Was sie macht ^ Download ^ | **ADC Connect** | Verbindet sich automatisch mit einem vorgegebenen Wi-Fi und aktiviert ADB über Wi-Fi. | [[https://git.aiwaysdrivers.org/aiwaysdrivers/openaiways/raw/branch/main/android-connect/openaiways-connect.apk|adc-connect.apk]] | | **ADC Telemetry** | Liest CAN-Signale und veröffentlicht sie über MQTT mit Home-Assistant-Auto-Discovery. | {{:adc_telemetry.apk|adc-telemetry.apk}} | | **ADC Terminal** | Ein VT100-Terminal mit erweiterter Tastatur; läuft als System — oder als **root**, wenn du den **su**-Knopf drückst. | {{:adc_terminal.apk|adc-terminal.apk}} | | **ADC Speedwarning** | Zeigt das aktuelle Tempolimit auf dem Fahrerdisplay und warnt, wenn du es überschreitest — vollständig offline, aus einem bordeigenen Kartenindex. **Einstellbar**: Warnton an/aus, ab wie viel km/h über dem Limit gewarnt wird (0–20 km/h) und die Lautstärke. | [[https://git.aiwaysdrivers.org/aiwaysdrivers/openaiways/raw/branch/main/speedwarning/openaiways-speedwarning.apk|adc-speedwarning.apk]] ([[https://git.aiwaysdrivers.org/aiwaysdrivers/openaiways/src/branch/main/speedwarning|Quellcode]]) | ==== Installieren ==== - Das ''.apk'' per Sideload aufspielen (auf einen USB-Stick kopieren oder direkt auf dem Gerät herunterladen) — den Weg über den Dateimanager findest du unter [[de:access|So kommst du rein]]. - **Jede App nach der Installation einmal öffnen.** Android hält eine frisch installierte App im Zustand „stopped“, in dem sie den Boot-Broadcast nicht empfängt — dieser erste manuelle Start ist also das, was den Autostart scharf macht. - Konfigurieren (siehe unten). Connect und Telemetry **starten danach bei jedem Neustart automatisch**; Terminal startest du von Hand, wenn du eine Shell brauchst. ==== ADC Connect ==== Trag deine Wi-Fi-Netze ein (SSID + Passwort, als Prioritätsliste) und setze das Häkchen bei **ADB**. Nach dem Booten verbindet die App das Wi-Fi neu und aktiviert adb über Wi-Fi wieder. Quelle: https://git.aiwaysdrivers.org/aiwaysdrivers/openaiways/src/branch/main/android-connect ==== ADC Telemetry ==== Gib deinen MQTT-Broker ein (Host, Port, Benutzer, Passwort) sowie ein Basis-Topic. Mit Home-Assistant-Auto-Discovery erscheint das Auto automatisch — Ladezustand, Spannung, Strom, Reichweite, Ladevorgang und mehr. ==== ADC Terminal ==== Ein richtiges Terminal (basiert auf jackpals emulatorview) mit eigener US-Bildschirmtastatur, sodass die IME des Geräts nicht gebraucht wird. * Die Taste **''su''** schaltet die Shell auf **root** und zurück — wenn du root bist, steht dort **''system''**. Root ist ein echtes PTY mit ''uid 0'', bereitgestellt vom lokalen adbd. **Warnung – als root kannst du alles tun, auch dein System zerschießen. Nutzung auf eigenes Risiko.** * Das **×** oben rechts schließt das Terminal. * **Nur ein adb-Client gleichzeitig:** Der adbd des Geräts bedient nur eine Verbindung. Solange das Terminal die Root-Shell hält, kann sich das ''adb'' eines Laptops nicht verbinden (und umgekehrt). Verlässt oder schließt du das Terminal, wird adb automatisch wieder frei. {{:terminal_keyboard.png?600|ADC Terminal — integrierte US-Tastatur und root/su-Umschalter}} ==== ADC Speedwarning ==== Zeigt das aktuelle **Tempolimit** auf dem Fahrerdisplay und blinkt + piept, wenn du schneller fährst — vollständig **offline**, ohne Cloud und ohne OEM-Daten. **So funktioniert es:** Die aktuelle Geschwindigkeit kommt vom **CAN-Bus**, die Position von **GPS**. Ein bordeigener **HMM-Map-Matcher** (im Stil von Newson–Krumm) passt den GPS-Track an die //Straßenfolge// in einem Offline-**OpenStreetMap**-Index an — so bleibt er unter Brücken, in Tunneln (dort läuft er auf CAN-Odometrie weiter, bis GPS wieder greift) und an Parallelstraßen vorbei auf der richtigen Straße und liest dann deren Limit aus (inklusive zeitabhängiger Zonen im Stil //„30 km/h 07–19h“//). Das Schild wird auf dem erreichbaren **Fahrerdisplay** gezeichnet (siehe [[de:architecture|Architektur]]). **Der Kartenindex (erforderlich):** Die App liest einen Offline-Index mit Straßen und Tempolimits unter ''/sdcard/region_route.sqlite''. Ein fertiger: * {{:region_route.sqlite|region_route.sqlite}} — Region **Berlin / Brandenburg** (~34 MB; 144k Straßen, 129k mit Limit, 4.879 zeitabhängige Zonen, 311 Tunnel; bbox lat 52.07–52.68, lng 12.67–14.74). Für ein anderes Gebiet baust du dir deinen eigenen Index aus OpenStreetMap mit der Map-Matcher-Pipeline (Quellcode folgt). Ohne Index läuft die App, zeigt aber kein Limit. **Installation:** - ''adc-speedwarning.apk'' per Sideload aufspielen und **einmal öffnen** (das macht den Autostart scharf; danach läuft sie bei jedem Boot). - Den Index als ''/sdcard/region_route.sqlite'' auf das Gerät legen (z. B. ''adb push region_route.sqlite /sdcard/''), dann auf **Restart service** tippen. Im Statusbildschirm sollte //Map DB: loaded// stehen. - Losfahren — das Limit erscheint auf dem Fahrerdisplay und warnt dich, wenn du drüber bist. //Außerdem zeichnet die App deine Fahrten in ''/sdcard/aiways_track.csv'' auf (größenbegrenzt, automatisch rotiert auf ≤32 MB), um den Matcher zu verbessern.// ===== Was du für eigene Software brauchst ===== * **Android Studio** (eine beliebige aktuelle Version) + das **Android SDK**. Das Gerät läuft mit **Android 4.4.2 (API 19)**, setze also **''minSdkVersion 19''** (''compileSdk'' / ''targetSdk'' dürfen höher sein). Die ABI ist **armeabi-v7a** — liefere keine nativen Bibliotheken aus, die nur arm64/x86 unterstützen. * Ein **JDK** (das mit Android Studio gelieferte genügt). * **''adb''** (Android platform-tools) in deinem ''PATH''. ===== ADB über Wi-Fi ===== Das Gerät betreibt adb über TCP und hat **''ro.adb.secure=0''** gesetzt (keine Rückfrage zur Schlüssel-Authentifizierung). Im Heim-Wi-Fi ist es unter **'':5555''** erreichbar. adb connect :5555 adb devices # -> :5555 device Falls adb über TCP nicht läuft, aktiviere es aus einer **Root-Shell auf dem Gerät**: ''setprop service.adb.tcp.port 5555'' und dann ''stop adbd; start adbd''. ===== Signieren — der Platform-Key ===== Mehrere dieser Apps deklarieren **''sharedUserId="android.uid.system"''** und nutzen Berechtigungen der Stufe ''signature'', müssen also mit dem **Platform-Key** signiert werden — dem Key, mit dem das Framework des Geräts selbst signiert ist. Android gewährt diese System-Identität nur einer App, deren Signaturzertifikat zu dem der Plattform passt. **Die Head-Unit hat nie einen eigenen Key bekommen.** (jedenfalls bei meiner Firmware 1.7.0) Es ist ein Freescale/NXP-**i.MX6-Android-BSP**-Build, und der OEM hat ihn mit dem **öffentlichen Testschlüssel** des BSP ausgeliefert statt mit einem privaten Release-Key — eine App mit genau diesem öffentlichen Key zu signieren genügt also, um als System zu laufen. Der Key ist selbstsigniert: Subject : C=US, O=Android, CN=Android, emailAddress=android@freescale.com Valid : 2011-07-14 -> 2038-11-29 SHA-256 : 7F:BA:E8:17:B7:DB:24:64:2D:89:59:C3:47:B5:61:C0:03:C6:CF:DE:2C:B1:0F:90:9C:93:2F:21:A4:D6:D8:04 Weil dieser Key **öffentlich** ist, kann jeder eine App mit System-Rechten für dieses Gerät signieren — ein Sicherheitsversäumnis des OEM und genau das, was dieses Projekt möglich macht. NXP hat denselben Key rund ein Jahrzehnt lang in jedem i.MX-BSP wiederverwendet, er ist also leicht zu finden. ==== Woher du ihn bekommst ==== Er liegt im i.MX-Device-Tree unter ''common/security/'': ''platform.pk8'' (privater Schlüssel) und ''platform.x509.pem'' (Zertifikat). Ein öffentlicher Spiegel: https://github.com/Avnet/android-imx-device-fsl/tree/maaxboard_android_p9.0.0_1.0.0/common/security Prüfe, ob du den richtigen hast — das Zertifikat muss zum Fingerprint oben passen: openssl x509 -in platform.x509.pem -noout -fingerprint -sha256 ==== Keystore anlegen und bauen ==== Mach aus dem BSP-Schlüsselpaar einen Keystore, den Gradle nutzen kann (''platform.pk8'' ist DER PKCS#8): openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.key.pem openssl pkcs12 -export -in platform.x509.pem -inkey platform.key.pem -name platform -out platform.p12 -passout pass:android Richte den ''signingConfig'' der App auf ''platform.p12'' (Store- und Key-Passwort ''android'', Alias ''platform''), dann bauen und installieren: ./gradlew :app:assembleDebug adb -s :5555 install -r app/build/outputs/apk/debug/app-debug.apk ''install -r'' ersetzt die App an ihrem Platz und **scheitert sauber bei einer Signatur-Abweichung** (die alte App bleibt erhalten) — ein Versuch ist also gefahrlos. //Alternativ legst du denselben Key unter ''~/.android/debug.keystore'' ab, dann sind ganz normale Debug-Builds plattform-signiert, ohne ''signingConfig''.// ===== Mit dem Auto aus einer App sprechen ===== Fahrzeugdaten und Kommandos laufen über zwei **gebundene** OEM-Services (Bind über Intent-Action + Package — sie stehen nicht im ServiceManager, ein ''service call'' aus der Shell erreicht sie also nicht): ^ Service ^ Bind (Action / Package) ^ Interface ^ Verwendung ^ | **Canbus** | ''action.adayo.CANBUSSERVICE'' / ''com.adayo.canbus'' | ''ICanbusService'' | ''getInt/getFloat/getIntArray(key)'' zum Lesen, ''sendData(action,val)'' zum Kommandieren — die [[de:cansignals|Signal-Keys]] | | **CarManager** | ''action.adayo.CARSERVICE'' / ''com.adayo.carmanager'' | ''ICarService'' | Audio / EQ, Radio, ''mcu_writeDataToMcu'' (rohe MCU-Frames) | Nimm das AIDL-Interface mit, oder rufe über ein rohes Binder-''transact()'' auf. Skizze (Canbus): bindService(new Intent("action.adayo.CANBUSSERVICE").setPackage("com.adayo.canbus"), conn, BIND_AUTO_CREATE); // in onServiceConnected: ICanbusService s = ICanbusService.Stub.asInterface(binder); int soc = s.getInt(3457); // pack-1 SoC % float v = s.getFloat(3455); // pack-1 voltage V s.sendData(103, 1); // A/C ON (⚠ actuates the car) ⚠ Achtung: ''sendData'' betätigt das Auto wirklich — die letzte Zeile der Skizze schaltet die Klimaanlage ein. ===== CAN-Probing ohne eigenen Code ===== Um Keys ohne eigene App auszuprobieren, hat **[[de:dev#adc_telemetry|ADC Telemetry]]** einen eingebauten Prober (es bindet ''ICanbusService'' ohnehin schon) — lies oder kommandiere jeden [[de:cansignals|Key]] direkt aus adb. Siehe **[[de:canbus#signale_live_abfragen|CAN-Bus → Signale live ausprobieren]]**. ===== Außerdem: der ESP32-S3-Begleiter (separate Hardware) ===== Keine Head-Unit-App — ein eigenständiger **ESP32-S3**, den du ins Auto einbaust, für Leute, die gar nicht auf die Head-Unit wollen (oder nicht draufkommen). Ein Board macht vier Dinge gleichzeitig: * **Spricht per BLE mit der T-Box** (BlueGate-Protokoll) → **Vorklimatisierung** und **Fernsteuerung** (Ver-/Entriegeln, Lichthupe, Heckklappe, Fenster). * **Liest einen BLE-OBD2-Dongle** (ELM327) → Ladezustand, HV-Spannung/-Strom, Zellspannungen, Temperaturen; im Flash gehalten, damit die letzten bekannten Werte erhalten bleiben, wenn das Auto aus oder nicht erreichbar ist. * **Veröffentlicht über MQTT mit Home-Assistant-Auto-Discovery** — Sensoren sowie die Bedienelemente Precondition/Lock/Unlock/Flash/Trunk erscheinen automatisch in HA. * **Betreibt einen Wi-Fi-Hotspot + Web-Dashboard** gleichzeitig mit der Verbindung ins Heim-Wi-Fi bzw. zu MQTT, sodass du auch dann per Handy steuern und überwachen kannst, wenn kein Heim-Wi-Fi in der Nähe ist. Firmware-Updates gehen nach dem ersten USB-Flash **über Wi-Fi** raus. Ein vorgebautes Image und ein Flasher im Browser (keine Toolchain nötig) liegen auf seiner eigenen Seite: https://git.aiwaysdrivers.org/aiwaysdrivers/openaiways/src/branch/main/esp32-companion //🤖 KI-unterstützte Entwicklung — geprüft, bevor man ihr an einem echten Fahrzeug vertraut, gleicher Haftungsausschluss wie bei den Apps oben.//