Häufig gestellte Fragen

Hat Google A/B-OTAs auf Geräten verwendet?

Ja. Der Marketingname für A/B-Updates ist nahtlose Updates. Die im Oktober 2016 ausgelieferten Pixel- und Pixel XL-Smartphones hatten A/B-Partitionen und alle Chromebooks verwenden dieselbe update_engine-Implementierung von A/B. Die erforderliche Implementierung des Plattformcodes ist in Android 7.1 und höher öffentlich.

Warum sind A/B-OTAs besser?

A/B-OTAs bieten eine bessere Nutzererfahrung bei der Installation von Updates. Messungen aus monatlichen Sicherheitsupdates zeigen, dass diese Funktion bereits ein Erfolg ist: Im Mai 2017 hatten 95% der Pixel-Nutzer nach einem Monat das aktuelle Sicherheitsupdate installiert, verglichen mit 87% der Nexus-Nutzer. Außerdem aktualisieren Pixel-Nutzer schneller als Nexus-Nutzer. Wenn Blöcke während eines OTA-Updates nicht aktualisiert werden können, führt das nicht mehr dazu, dass ein Gerät nicht mehr startet. Bis das neue System-Image erfolgreich gestartet wurde, kann Android auf das vorherige funktionierende System-Image zurückgreifen.

Was ist „system_other“?

Anwendungen werden in APK-Dateien gespeichert, die eigentlich ZIP-Archive sind. Jede APK-Datei enthält eine oder mehrere DEX-Dateien mit portablem Dalvik-Bytecode. Eine .odex-Datei (optimierte .dex-Datei) wird separat von der .apk-Datei gespeichert und kann gerätespezifischen Maschinencode enthalten. Wenn eine .odex-Datei verfügbar ist, kann Android Anwendungen mit Ahead-of-Time-Kompilierungsgeschwindigkeit ausführen, ohne dass der Code bei jedem Start der Anwendung kompiliert werden muss. Eine .odex-Datei ist nicht unbedingt erforderlich: Android kann den .dex-Code direkt über die Interpretation oder die Just-In-Time-Kompilierung (JIT) ausführen. Eine .odex-Datei bietet jedoch die beste Kombination aus Start- und Laufzeitgeschwindigkeit, sofern Speicherplatz verfügbar ist.

Beispiel: Für die Datei „installed-files.txt“ eines Nexus 6P mit Android 7.1 und einer Gesamtgröße des System-Images von 2.628 MiB (2.755.792.836 Byte) sieht die Aufschlüsselung der größten Beiträge zur Gesamtgröße des System-Images nach Dateityp so aus:

.odex 1391770312 Byte 50,5%
.apk 846878259 Byte 30,7%
.so (nativer C/C++-Code) 202162479 Byte 7,3%
OAT-Dateien/ART-Images 163892188 Byte 5,9 %
Schriftarten 38952361 Byte 1,4 %
ICU-Sprachdaten 27468687 Byte 0,9 %

Diese Zahlen sind auch für andere Geräte ähnlich. Auf Nexus-/Pixel-Geräten belegen .odex-Dateien also etwa die Hälfte der Systempartition. Das bedeutete, dass wir weiterhin ext4 verwenden konnten, aber die .odex-Dateien in der Fabrik auf die B-Partition schreiben und sie dann beim ersten Start auf /data kopieren konnten. Der tatsächlich verwendete Speicherplatz mit ext4 A/B ist identisch mit SquashFS A/B, da wir bei Verwendung von SquashFS die voroptimierten .odex-Dateien auf system_a anstelle von system_b ausgeliefert hätten.

Wenn .odex-Dateien nach /data kopiert werden, geht der auf /system gesparte Speicherplatz dann nicht auf /data verloren?

Nicht ganz. Auf Pixel-Geräten wird der größte Teil des von .odex-Dateien belegten Speicherplatzes für Apps verwendet, die sich in der Regel auf /data befinden. Diese Apps erhalten Google Play-Updates. Die APK- und ODEX-Dateien im System-Image werden daher während des größten Teils der Lebensdauer des Geräts nicht verwendet. Solche Dateien können vollständig ausgeschlossen und durch kleine, profildatenbasierte .odex-Dateien ersetzt werden, wenn der Nutzer die jeweilige App tatsächlich verwendet. So wird kein Speicherplatz für Apps benötigt, die der Nutzer nicht verwendet. Weitere Informationen finden Sie im Google I/O 2016-Talk The Evolution of Art.

Der Vergleich ist aus mehreren Gründen schwierig:

  • Bei Apps, die über Google Play aktualisiert werden, befinden sich die .odex-Dateien immer auf /data, sobald sie ihr erstes Update erhalten.
  • Für Apps, die der Nutzer nicht ausführt, ist überhaupt keine .odex-Datei erforderlich.
  • Bei der profildatenbasierten Kompilierung werden kleinere .odex-Dateien als bei der Ahead-of-Time-Kompilierung generiert, da nur leistungsrelevanter Code optimiert wird.

Weitere Informationen zu den für OEMs verfügbaren Optimierungsoptionen finden Sie unter ART konfigurieren.

Gibt es nicht zwei Kopien der .odex-Dateien unter /data?

Das ist etwas komplizierter: Nachdem das neue System-Image geschrieben wurde, wird die neue Version von dex2oat für die neuen .dex-Dateien ausgeführt, um die neuen .odex-Dateien zu generieren. Dies geschieht, während das alte System noch ausgeführt wird. Die alten und neuen .odex-Dateien befinden sich also gleichzeitig auf /data.

Der Code in OtaDexoptService (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/OtaDexoptService.java) ruft getAvailableSpace auf, bevor jedes Paket optimiert wird, um eine Überfüllung von /data zu vermeiden. Beachten Sie, dass die Angabe verfügbar hier immer noch konservativ ist. Sie gibt den verbleibenden Speicherplatz vor dem Erreichen des üblichen Schwellenwerts für geringen Speicherplatz des Systems an (gemessen sowohl als Prozentsatz als auch als Byteanzahl). Wenn /data voll ist, gibt es also nicht zwei Kopien jeder .odex-Datei. Derselbe Code hat auch einen BULK_DELETE_THRESHOLD: Wenn das Gerät sich dem verfügbaren Speicherplatz nähert (wie gerade beschrieben), werden die .odex-Dateien von Apps entfernt, die nicht verwendet werden. Das ist ein weiterer Fall ohne zwei Kopien jeder .odex-Datei.

Im schlimmsten Fall, wenn /data vollständig belegt ist, wird das Update erst durchgeführt, wenn das Gerät in das neue System neu gestartet wurde und die .odex-Dateien des alten Systems nicht mehr benötigt werden. Der PackageManager übernimmt diese Aufgabe: (frameworks/base/+/android16-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215). Nachdem das neue System erfolgreich gestartet wurde, kann installd (frameworks/native/+/android16-release/cmds/installd/dexopt.cpp#2422) die vom alten System verwendeten .odex-Dateien entfernen. Das Gerät befindet sich dann wieder im stabilen Zustand mit nur einer Kopie.

Es ist also möglich, dass /data zwei Kopien aller .odex-Dateien enthält. Dies ist jedoch (a) nur vorübergehend und (b) tritt nur auf, wenn Sie ohnehin viel freien Speicherplatz auf /data hatten. Außer während eines Updates gibt es nur eine Kopie. Im Rahmen der allgemeinen Robustheitsfunktionen von ART werden /data ohnehin nie mit .odex-Dateien gefüllt, da dies auch auf einem Nicht-A/B-System ein Problem wäre.

Erhöht das viele Schreiben und Kopieren nicht den Verschleiß des Flash-Speichers?

Nur ein kleiner Teil des Flash-Speichers wird neu geschrieben: Bei einem vollständigen Pixel-Systemupdate werden etwa 2,3 GiB geschrieben. Apps werden auch neu kompiliert, aber das gilt auch für Geräte ohne A/B-Partitionen. Bei herkömmlichen blockbasierten vollständigen OTAs wurde eine ähnliche Datenmenge geschrieben, sodass die Flash-Verschleißraten ähnlich sein sollten.

Wird die Zeit für das Flashen im Werk verlängert, wenn zwei Systempartitionen geflasht werden?

Nein. Die Größe des Systemabbilds auf Pixel hat sich nicht erhöht. Der Speicherplatz wurde lediglich auf zwei Partitionen aufgeteilt.

Verlangsamt das Beibehalten von .odex-Dateien auf B das Neustarten nach dem Zurücksetzen auf die Werkseinstellungen?

Ja. Wenn Sie ein Gerät tatsächlich verwendet, ein OTA-Update durchgeführt und die Daten auf Werkseinstellungen zurückgesetzt haben, dauert der erste Neustart länger als sonst (1 Minute und 40 Sekunden im Vergleich zu 40 Sekunden auf einem Pixel XL), da die .odex-Dateien nach dem ersten OTA-Update aus B verloren gegangen sind und daher nicht in /data kopiert werden können. Das ist der Kompromiss.

Das Zurücksetzen auf die Werkseinstellungen sollte im Vergleich zum normalen Start nur selten erfolgen. Daher ist die dafür benötigte Zeit weniger wichtig. Das betrifft keine Nutzer oder Rezensenten, die ihr Gerät direkt vom Hersteller erhalten, da in diesem Fall die B-Partition verfügbar ist. Durch die Verwendung des JIT-Compilers müssen wir nicht alles neu kompilieren. Es ist also nicht so schlimm, wie Sie vielleicht denken. Apps können auch über coreApp="true" im Manifest als Apps markiert werden, für die eine Ahead-of-Time-Kompilierung erforderlich ist: (frameworks/base/+/android16-release/packages/SystemUI/AndroidManifest.xml#23). Dies wird derzeit von system_server verwendet, da aus Sicherheitsgründen kein JIT-Kompilieren zulässig ist.

Verlangsamt das Beibehalten von .odex-Dateien unter /data anstelle von /system das Neustarten nach einem OTA?

Nein. Wie oben beschrieben, wird das neue dex2oat ausgeführt, während das alte System-Image noch aktiv ist, um die Dateien zu generieren, die für das neue System benötigt werden. Das Update gilt erst als verfügbar, wenn diese Arbeiten abgeschlossen sind.

Können (sollten) wir ein A/B-Gerät mit 32 GiB versenden? 16 GiB? 8 GiB?

32 GiB funktionieren gut, da sie sich auf Pixel bewährt haben. 320 MiB von 16 GiB bedeuten eine Reduzierung von 2%. Ebenso entspricht 320 MiB von 8 GiB einer Reduzierung um 4%. Auf Geräten mit 4 GiB ist A/B natürlich nicht die empfohlene Wahl, da der Overhead von 320 MiB fast 10% des insgesamt verfügbaren Speicherplatzes ausmacht.

Sind für AVB2.0 A/B-OTAs erforderlich?

Nein. Für Android Verified Boot waren schon immer blockbasierte Updates erforderlich, aber nicht unbedingt A/B-Updates.

Ist für A/B-OTAs AVB2.0 erforderlich?

Nein.

Wird der Rollback-Schutz von AVB2.0 durch A/B-OTAs unterbrochen?

Nein. Hier gibt es einige Verwirrung, da ein A/B-System, das nicht in das neue System-Image booten kann, nach einer bestimmten Anzahl von Wiederholungsversuchen, die von Ihrem Bootloader festgelegt werden, automatisch zum „vorherigen“ System-Image zurückkehrt. Der entscheidende Punkt ist jedoch, dass „vorherig“ im Sinne von A/B tatsächlich immer noch das „aktuelle“ System-Image ist. Sobald auf dem Gerät ein neues Image gebootet wurde, wird der Rollback-Schutz aktiviert und verhindert, dass Sie zum vorherigen Image zurückkehren können. Bis Sie das neue Image erfolgreich gebootet haben, wird es von der Rollback-Schutzfunktion nicht als aktuelles System-Image betrachtet.

Wenn Sie ein Update installieren, während das System ausgeführt wird, ist das nicht langsam?

Bei Nicht-A/B-Updates soll das Update so schnell wie möglich installiert werden, da der Nutzer wartet und sein Gerät während der Installation des Updates nicht verwenden kann. Bei A/B-Updates ist es genau umgekehrt. Da der Nutzer sein Gerät weiterhin verwendet, soll das Update so wenig Auswirkungen wie möglich haben. Es wird daher bewusst langsam durchgeführt. Über die Logik im Java-Systemupdate-Client (für Google ist das GmsCore, das von GMS bereitgestellte Kernpaket) versucht Android auch, einen Zeitpunkt auszuwählen, zu dem die Nutzer ihre Geräte nicht verwenden. Die Plattform unterstützt das Pausieren und Fortsetzen des Updates. Der Client kann das Update pausieren, wenn der Nutzer das Gerät verwendet, und fortsetzen, wenn das Gerät wieder im Leerlauf ist.

Ein OTA-Update umfasst zwei Phasen, die in der Benutzeroberfläche unter der Fortschrittsanzeige deutlich als Schritt 1 von 2 und Schritt 2 von 2 angezeigt werden. Schritt 1 entspricht dem Schreiben der Datenblöcke, während in Schritt 2 die .dex-Dateien vorkompiliert werden. Diese beiden Phasen unterscheiden sich hinsichtlich der Auswirkungen auf die Leistung. Die erste Phase ist die einfache Ein-/Ausgabe. Dafür sind nur wenige Ressourcen (RAM, CPU, E/A) erforderlich, da nur langsam Blöcke kopiert werden.

In der zweiten Phase wird dex2oat ausgeführt, um das neue System-Image vorzukompilieren. Die Anforderungen sind hier natürlich weniger klar, da tatsächliche Apps kompiliert werden. Das Kompilieren einer großen und komplexen App ist natürlich mit viel mehr Aufwand verbunden als das Kompilieren einer kleinen und einfachen App. In Phase 1 gibt es jedoch keine Festplattenblöcke, die größer oder komplexer sind als andere.

Der Vorgang ist ähnlich wie bei der Installation eines App-Updates durch Google Play im Hintergrund, bevor die Benachrichtigung 5 Apps aktualisiert angezeigt wird. Das ist seit Jahren so.

Was ist, wenn ein Nutzer tatsächlich auf das Update wartet?

Bei der aktuellen Implementierung in GmsCore wird nicht zwischen Hintergrundupdates und vom Nutzer initiierten Updates unterschieden. Das kann sich in Zukunft jedoch ändern. Wenn der Nutzer explizit darum gebeten hat, dass das Update installiert wird, oder sich den Fortschritt des Updates ansieht, priorisieren wir die Updatearbeiten, da wir davon ausgehen, dass er aktiv darauf wartet, dass das Update abgeschlossen wird.

Was passiert, wenn ein Update nicht angewendet werden kann?

Bei Nicht-A/B-Updates blieb der Nutzer in der Regel mit einem unbrauchbaren Gerät zurück, wenn ein Update nicht angewendet werden konnte. Die einzige Ausnahme war, wenn der Fehler auftrat, bevor eine Anwendung überhaupt gestartet wurde (z. B. weil das Paket nicht überprüft werden konnte). Bei A/B-Updates wirkt sich ein Fehler beim Anwenden eines Updates nicht auf das aktuell ausgeführte System aus. Das Update kann einfach später noch einmal versucht werden.