China-Handy – Teil 3

Posted on So 14 Februar 2021 in Computer & Electronics

Wie ihr im letzen Post lesen konntet, hatte ich es erfolgreich geschafft, mein neues Xiaomi Redmi Note 9 Pro zu bricken. Inzwischen hat es einen kleinen touristischen Ausflug nach Flensburg hinter sich (zu Ingram Micro, die in Deutschland die Reparaturen für Xiaomi machen). Nun geht es wieder, allerdings natürlich mit der Stock-Firmware, die neu geflasht wurde. Also habe ich alle Schritte aus dem letzten Post erneut absolviert (also bis auf Bootloader Sperren natürlich) und habe nun ein laufendes Xiaomi.eu System.

Im Großen und Ganzen gefällt mir das OS ganz gut, aber es enthält noch immer einige Dinge, die ich nicht haben will. Z.B. diese komische App-Vault App, die sich auf dem -1 Screen eingenistet hat und mich mit vielen chinesischen Schriftzeichen begrüßt. Und natürlich sind auch alle Standard Apps, wie Kontakte, Phone, Kalender, File-Browser etc. in der MI-Version installiert und jede davon begrüßt mich beim ersten Öffnen mit den Datenschutzbedingungen, in die ich erstmal einwilligen soll. Das finde ich natürlich suboptimal. Am liebsten wäre mir eigentlich ein völlig unverändertes Android-System, ohne "Verbesserungen" vom Hersteller. Entsprechende Projekte gibt es natürlich, aber die haben aktuell noch keine als stable oder official gekennzeichneten ROMs für mein Modell released. Also vorerst Xiaomi.eu.

Entschlackungskur

Nun ist es nicht so, dass man da nichts unternehmen könnte, um das System ein wenig zu fine-tunen. Mit anderen Worten: heute wollen wir mal Apps löschen.

Nun ist es so, dass sich gerade die mitgelieferten System-Apps nicht einfach so deinstallieren lassen. Manche kann man zumindest deaktivieren, viele aber auch nicht. Aber dagegen ist ein Kraut gewachsen und das heißt adb. Auch störrische Apps lassen sich per USB-Debugging deaktivieren oder deinstallieren und entgegen der landläufigen Meinung muss das Telefon dazu nicht gerootet werden. Und das geht so:

  • Sicherstellen, dass USB debugging und install via USB aktiviert sind (siehe letzter Post).
  • Telefon via USB mit dem Computer verbinden
  • Ggf. am Telefon den USB-Debugging-Zugriff bestätigen

Nun können wir uns auf dem Telefon einen shell-Zugang holen.

adb shell

Und schon befinden wir uns in einer LINUX-Shell in der wir arbeiten können. Der Paket-Manger von Android hat den schönen Namen pm. Und mit dem können wir uns alle installierten Apps anzeigen lassen

joyeuse:/ $ pm list packages
package:com.android.cts.priv.ctsshim
package:com.qualcomm.qti.qms.service.telemetry
package:com.qualcomm.qti.qcolor
package:com.android.internal.display.cutout.emulation.corner
package:com.google.android.ext.services
[...]
package:com.termux
[...]

... Apps deaktivieren

pm disable-user com.termux

... wieder aktivieren

pm enable com.termux

... oder deinstallieren.

# uninstall and wipe data
pm uninstall --user 0 com.termux

# uninstall but keep data
pm uninstall -k --user 0 com.termux

Das --user 0 spezifiziert, dass die Deinstallation für User 0 ausgeführt werden soll. Das ist der Hauptbenutzer des Handies.

Und schon sind wir mitten im Android Paket-Namens-Chaos. Für jede App gibt es nämlich drei verschiedene Namen/Bezeichnungen, die hier eine Rolle spielen:

  1. Anzeigename – also der Name unter dem die App unter Settings > Apps aufgeführt wird. Dieser Name steht gewöhnlich auch unter dem Icon. z.B. "Kalender"
  2. Package Name – also das womit das pm Kommando arbeitet. z.B. com.google.android.calendar
  3. APK-Dateiname – also der Name der Installationsdatei.

Und wie kriege ich nun raus, welche dieser, teils kryptisch benannten, Pakete ich loswerden will? Dazu gibt es mehre Hilfsmittel. Nehmen wir mal an, wir wollen die Xiaomi Fitness-App Mi fit loswerden und haben keine Ahnung, wie das dazugehörige Package heißt.

Diese App gibt's im Google Play Store und der einfachste Weg führt über diesen. Geht mit dem Browser Eures Vertrauens nach https://play.google.com, sucht dort nach der App und geht auf die gefundene App-Seite:

Play Store Screenshot

Wie Ihr seht, steht der gesuchte Package-Name in der URL: com.xiaomi.hm.health.

Aber was, wenn eine App nicht aus dem Play Store kommt, sondern mit dem System kam? In dem Fall könnt Ihr die Paketliste von pm durchsuchen. Versuchen wir mal die Kalender-App zu finden:

joyeuse:/ $ pm list packages -f calendar
package:/system/priv-app/CalendarProvider/CalendarProvider.apk=com.android.providers.calendar
package:/data/app/com.google.android.calendar-YG-s2KnUClyb-YTvQBqlPg==/base.apk=com.google.android.calendar
package:/product/app/GoogleCalendarSyncAdapter/GoogleCalendarSyncAdapter.apk=com.google.android.syncadapters.calendar

oder

joyeuse:/ $ pm list packages | grep calendar                                                                                                                                                                    
package:com.android.providers.calendar
package:com.google.android.calendar
package:com.google.android.syncadapters.calendar

Hochmut

Auf diese Weise habe ich nun diverse Pakete identifiziert, die mir äußerst überflüssig vorkamen und ich habe angefangen, das eine oder andere zu löschen. Bei manchen Pakten war unklar, ob man die braucht, oder ob sie weg können und da hilft Google. Natürlich stößt man dabei unweigerlich auf die zahlreichen Xiaomi/Samsung/LG/... bloatware list-Seiten bei github, XDA-Developers und diverse Foren. Und dann wird man mutiger und fordert das Schicksal erneut heraus. Kurz – ich habe die Namen aller Pakete die mich überflüssig dünkten in ein Text-File kopiert (crap.txt) und dann alles schön automatisiert gelöscht. Nimm das, Du chinesisches Spionagewerkzeug!

xargs -L 1 adb shell pm uninstall --user 0 < crap.txt

Oder für Freunde der for-Schleife:

for i in `cat crap.txt` ; do adb shell pm uninstall --user 0 $i; done

Das funktioniert super! Und es ist sehr bequem – einfach alles rein kopieren, das man selber identifiziert hat, noch ein paar aus den obigen Listen dazu und man kann sogar Zeilen auskommentieren (wie gewohnt, ein # davor), dann scheitert die entsprechende Deinstallation, weil aus Sicht des pm Befehls ja kein Package angegeben wurde.

Sehr gut! (...lautes Siegesgebrüll...)

... kommt vor dem Fall.

Das fühlte sich richtig super an! Also jedenfalls bis das Handy anfing, sich komisch zu verhalten. Irgendwie ist der System-Launcher permanent abgeschmiert und offenbar hatte ich auch die Telefon-App gelöscht, denn sie war unauffindbar. Aber wer will schon telefonieren? Das mit dem Launcher konnte ich retten, indem ich schnell den Nova-launcher installiert haben, den ich eh schöner finde. Zwar kam ich nicht mehr an die App-Icons auf den normalen Screens ran, aber ich habe ein APK zum Download gefunden, dass ich dann via ADB und pm installieren konnte. In's Setup kam ich noch und konnte so den default Launcher wählen.

Offenbar waren nicht alle Apps, die ich gelöscht hatte so überflüssig, wie ich dachte. Grumpf!

Apps wieder installieren

Das mit der Phone App war leicht zu lösen – die gibt's im Playstore, wie Sand am Meer. Desgleichen, habe ich die Google Variante von Kalender, Kontakte etc. installiert und so insgesamt gefällt mir das nun alles schon ganz gut. Allerdings sind auch ein paar andere Kleinigkeiten auf der Strecke geblieben. Z.B. kann ich aktuell keine Klingeltöne mehr einstellen, weil das dann abstürzt. Offenbar hab ich da eine wichtige Komponente gelöscht (com.android.thememanager).

Das Problem dabei ist, dass es sich dabei zum Teil um System-Apps handelt, die man nicht einfach aus dem Play Store holen kann. Nun könnte ich natürlich das ROM einfach neu flashen und alles wäre wieder da, aber das habe ich im Laufe der letzten Blog-Post nun so oft gemacht, dass es mir inzwischen echt auf den Zeiger geht, danach jedes mal wieder alles neu einzurichten. Und überhaupt – das muss doch auch komplizierter gehen!?!

Aber woher nehmen, wenn nicht stehlen? Eine Möglichkeit besteht darin, mal den Paketnamen in die Suchmaschine Meines Vertrauens einzugeben und zu schauen, ob man das apk nicht zufällig auf APKmirror, oder anderswo finden kann. Dazu ist es hilfreich, diesen Paketnamen auch zu kennen und so war ich froh, meine crap.txt Liste zu haben.

Aber es geht meist noch simpler: Der uninstall Befehl hatte zwar das jeweilige Paket deinstalliert, aber nicht das apk-File gelöscht. Und das können wir nun erneut installieren. Z.B. für die Wallpaper-Verwaltung:

cmd package install-existing com.miui.miwallpaper

Das ist doch schön. Funktioniert aber nicht immer, denn einige APK-Files mussten scheinbar doch dran glauben:

joyeuse:/ $ cmd package install-existing com.miui.miwallpaper.earth                                                                                                                                             
android.content.pm.PackageManager$NameNotFoundException: Package com.miui.miwallpaper.earth doesn't exist

Bei einem Bild der Erde ist das zu verschmerzen, aber in anderen Fällen mag es problematischer sein.

Die App im Heuhaufen

Aber Moment mal – die fehlenden Pakete waren auf dem ROM drauf, das ich installiert habe. Das muss man doch irgendwie auspacken können! Also mal genauer ansehen. Mein ROM (xiaomi.eu_multi_HMNote9ProEU_V12.0.1.0.QJZMIXM_v12-10.zip) ist ein Zipfile – auspacken:

❯ unzip xiaomi.eu_multi_HMNote9ProEU_V12.0.1.0.QJZMIXM_v12-10.zip
❯ ll
-rw------- 1 phil phil   15458304 2008-02-29 02:33 boot.img
-rw------- 1 phil phil  185524870 2008-02-29 02:33 cust.new.dat.br
-rw------- 1 phil phil          0 2008-02-29 02:33 cust.patch.dat
-rw------- 1 phil phil       2118 2008-02-29 02:33 cust.transfer.list
-rw------- 1 phil phil        684 2008-02-29 02:33 dynamic_partitions_op_list
drwx------ 2 phil phil       4096 2008-02-29 02:33 firmware-update
drwx------ 3 phil phil       4096 2008-02-29 02:33 META-INF
-rw------- 1 phil phil  378467683 2008-02-29 02:33 product.new.dat.br
-rw------- 1 phil phil          0 2008-02-29 02:33 product.patch.dat
-rw------- 1 phil phil       8595 2008-02-29 02:33 product.transfer.list
-rw------- 1 phil phil 1291611334 2008-02-29 02:33 system.new.dat.br
-rw------- 1 phil phil          0 2008-02-29 02:33 system.patch.dat
-rw------- 1 phil phil      22475 2008-02-29 02:33 system.transfer.list
-rw------- 1 phil phil  503193350 2008-02-29 02:33 vendor.new.dat.br
-rw------- 1 phil phil          0 2008-02-29 02:33 vendor.patch.dat
-rw------- 1 phil phil      11370 2008-02-29 02:33 vendor.transfer.list

Keine Ahnung, warum die alle ein Datum in 2008 haben. Aber egal. Dieses system.new.dat.br File dürfte das Filesystem enthalten, dass wir brauchen. Nur was für ein Format ist das?

❯ file system.new.dat.br
system.new.dat.br: data

Hm. Wenig hilfreich. Eine Google-Suche später bin ich schlauer. Offenbar ist das ein eigenes Kompressionsformat mit dem selten dämlichen Namen brotli, das hier definiert wird: https://www.ietf.org/rfc/rfc7932.txt

Und es gibt ein Tool zum Ein- und Auspacken. Her damit und ausgepackt:

apt install brotli
brotli -d system.new.dat.br

Und schon haben wir ein File system.new.dat. Mal beschnuppern:

❯ file system.new.dat
system.new.dat: data

Na toll – und was ist das nun wieder? Auch da hilft eine kurze Recherche weiter. Wir haben ein sogenanntes sparse Android data image vor uns, das nun in ein richtiges Filesystem-Image verwandelt werden muss. Das tool dazu heißt sdat2img.py und ist auf github zu bekommen.

sdat2img.py system.transfer.list system.new.dat

Nun sprudelt eine gefühlte Million Meldungen in diesem Stil an uns vorbei:

Copying 143 blocks into position 295569...
Copying 512 blocks into position 298784...
Copying 512 blocks into position 294034...
Copying 512 blocks into position 8334...
Copying 512 blocks into position 293522...
Copying 512 blocks into position 473823...
Copying 512 blocks into position 21134...
Copying 512 blocks into position 293010...
Copying 512 blocks into position 292498...
Copying 512 blocks into position 552645...
Copying 512 blocks into position 108445...
Copying 512 blocks into position 108957...
Copying 512 blocks into position 380166...
Copying 512 blocks into position 102301...

Und am Ende haben wir eine Datei namens system.img, die nun endlich was handfestes ist:

❯ file system.img
system.img: Linux rev 1.0 ext2 filesystem data, UUID=4729639d-b5f2-5cc1-a120-9ac5f788683c (extents) (large files) (huge files)

Die können wir nun mounten:

❯ sudo mount system.img /mnt
mount: /mnt: wrong fs type, bad option, bad superblock on /dev/loop14, missing codepage or helper program, or other error.

... oder auch nicht. Was zum Geier ist jetzt schon wieder los???

❯ sudo dmesg
[...]
[29155.324896] EXT4-fs (loop14): couldn't mount RDWR because of unsupported optional features (4000)
[...]

Also wieder Google. Irgendein Problem mit nicht unterstützten Optionen, die mir relativ egal waren, als ich den entscheidenden Tip fand das read only zu mounten:

sudo mount -o ro system.img /mnt

Und siehe da – wir haben ein schönes gemountetes Filesystem. Also auf zur apk-Suche:

❯ find ./ -name *.apk
./system/priv-app/CallLogBackup/CallLogBackup.apk
./system/priv-app/VpnDialogs/VpnDialogs.apk
./system/priv-app/SharedStorageBackup/SharedStorageBackup.apk
./system/priv-app/Shell/Shell.apk
[...]
./system/app/EasterEgg/EasterEgg.apk
./system/app/HTMLViewer/HTMLViewer.apk
./system/app/mi_connect_service/mi_connect_service.apk
./system/app/SecureElement/SecureElement.apk
[...]

OK – besser. Nun bleibt noch herauszufinden, welche davon wir genau benötigen. Und leider haben die apk Files natürlich wieder andere Namen, als die Packages, die sie enthalten. Und dazu brauchen wir wieder mal eine weiteres Tool:

sudo apt install aapt

Damit kann man ein apk entsprechend befragen. Z.B.:

❯ aapt dump badging Calculator.apk | grep "package: name="
package: name='com.miui.calculator' versionCode='20120303' versionName='12.3.3' platformBuildVersionName=''

Und etwas systematischer:

find ./ -name *.apk -exec aapt dump badging {}  \; | grep "package: name\|application-label:"

Damit kann man arbeiten. D.h. ich werde mich nun mal durch die Liste arbeiten und sie mit meiner crap.txt Datei vergleichen.

Soviel für heute.