Gerätespezifischer Code

Das Wiederherstellungssystem enthält mehrere Hooks zum Einfügen von gerätespezifischem Code, sodass OTA Mit Updates können auch andere Teile des Geräts als das Android-System aktualisiert werden (z. B. das Baseband). oder Funkprozessor).

In den folgenden Abschnitten und Beispielen wird das tardis-Gerät angepasst, das vom yoyodyne-Anbieter verfügbar.

Partitionszuordnung

Ab Android 2.3 unterstützt die Plattform eMMc-Flash-Geräte und das ext4-Dateisystem, das ausgeführt wird. auf diesen Geräten. Es unterstützt auch Memory Technology Device (MTD)-Flash-Geräte und yaffs2. von älteren Releases.

Die Partitionszuordnungsdatei wird durch TARGET_RECOVERY_FSTAB angegeben. wird diese Datei sowohl vom das Wiederherstellungsbinärprogramm und die Paketerstellungstools. Sie können den Namen der Kartendatei in TARGET_RECOVERY_FSTAB in BoardConfig.mk

Eine Partitionszuordnungsdatei könnte beispielsweise so aussehen:

device/yoyodyne/tardis/recovery.fstab
# mount point       fstype  device       [device2]        [options (3.0+ only)]

/sdcard     vfat    /dev/block/mmcblk0p1 /dev/block/mmcblk0
/cache      yaffs2  cache
/misc       mtd misc
/boot       mtd boot
/recovery   emmc    /dev/block/platform/s3c-sdhci.0/by-name/recovery
/system     ext4    /dev/block/platform/s3c-sdhci.0/by-name/system length=-4096
/data       ext4    /dev/block/platform/s3c-sdhci.0/by-name/userdata

Mit Ausnahme des optionalen /sdcard-Objekts werden alle Bereitstellungspunkte in Beispiel muss definiert werden (Geräte können auch zusätzliche Partitionen hinzufügen). Es gibt fünf unterstützte Dateisystemtypen:

Yaffs2
Ein yaffs2-Dateisystem auf einem MTD-Flash-Gerät. "Gerät" muss der Name der MTD-Partition sein und muss auf /proc/mtd erscheinen.
Mtd.
Eine MTD-Rohpartition, die für bootfähige Partitionen wie Boot- und Wiederherstellungsvorgänge verwendet wird. MTD ist nicht bereitgestellt werden, aber der Bereitstellungspunkt dient als Schlüssel zum Auffinden der Partition. "Gerät" muss der Name der MTD-Partition in /proc/mtd sein.
Durchwahl 4
Ein ext4-Dateisystem auf einem eMMc-Flash-Gerät. "Gerät" muss der Pfad des blockorientierten Geräts sein.
Emmc
Rohe eMMc-Blockgerät, das für bootfähige Partitionen wie Booten und Wiederherstellen verwendet wird. Ähnlich wie Mtd-Typ hat, wird eMMc nie bereitgestellt, aber der String für den Bereitstellungspunkt dient dazu, Gerät in der Tabelle.
VFTT
Ein FAT-Dateisystem auf einem Blockgerät, in der Regel für externe Speicher wie eine SD-Karte. Die „Gerät“ ist das blockorientierte Gerät. "device2" ist ein zweites Blockgerät, das das System zu installieren versucht, das primäre Gerät kann nicht bereitgestellt werden (aus Gründen der Kompatibilität mit SD-Karten, die möglicherweise mit einer Partitionstabelle formatiert).

Alle Partitionen müssen im Stammverzeichnis bereitgestellt werden, d.h. der Wert des Bereitstellungspunkts muss mit einem Schrägstrich beginnen und keine anderen Schrägstriche enthalten. Diese Einschränkung gilt nur für die Dateisysteme für die Wiederherstellung; kann das Hauptsystem überall montiert werden. Verzeichnisse /boot, /recovery und /misc sollten Rohtypen sein (mtd oder emmc), während die Verzeichnisse /system, /data, /cache und /sdcard (falls verfügbar) sollten Dateisystemtypen sein (yaffs2, ext4 oder vfat).

Ab Android 3.0 erhält die Datei „recovery.fstab“ ein zusätzliches optionales Feld, Optionen. Derzeit ist die einzige Option length , mit der Sie explizit die Länge der Partition an. Diese Länge wird bei der Neuformatierung der Partition verwendet z.B. für die Nutzerdatenpartition während einer Datenlöschung oder auf die Werkseinstellungen Systempartition während der Installation eines vollständigen OTA-Pakets) Wenn der Wert für die Länge negativ ist, wird die zu formatierende Größe berechnet, indem der Wert für die Länge zur tatsächlichen Partitionsgröße addiert wird. Für Instanz, Festlegen von "length=-16384" bedeutet, dass die letzten 16k dieser Partition nicht wird überschrieben, wenn die Partition neu formatiert wird. Dies unterstützt Funktionen wie die Verschlüsselung von die Partition für Nutzerdaten, in der Verschlüsselungsmetadaten am Ende der Partition nicht überschrieben werden darf).

Hinweis:Die Felder device2 und options sind optional. Unklarheiten beim Parsen. Wenn der Eintrag im vierten Feld der Zeile mit einem Schrägstrich („/“) beginnt wird als device2 -Eintrag betrachtet. Der Eintrag beginnt nicht mit einem Schrägstrich („/“). wird es als Optionsfeld angesehen.

Startanimation

Gerätehersteller können die Animation anpassen, die angezeigt wird, wenn ein Android-Gerät startet. Erstellen Sie dazu eine ZIP-Datei, die gemäß dem Spezifikationen in Bootanimation-Format.

Für Android Things-Geräte können Sie die ZIP-Datei in die Android Things-Konsole hochladen, damit die Bilder das ausgewählte Produkt.

Hinweis:Diese Bilder müssen den Markenrichtlinien von Android entsprechen. Markenrichtlinien finden Sie im Abschnitt zu Android Partnermarketing Hub

Benutzeroberfläche für die Wiederherstellung

Zur Unterstützung von Geräten mit unterschiedlicher verfügbarer Hardware (z. B. physische Tasten, LEDs oder Bildschirme) können Sie die Wiederherstellungsoberfläche anpassen, um den Status anzuzeigen und auf manuell versteckte Funktionen für jedes Gerät.

Ihr Ziel ist es, eine kleine statische Bibliothek mit einigen C++-Objekten zu erstellen, gerätespezifische Funktionen nutzen können. Die Datei bootable/recovery/default_device.cpp wird standardmäßig verwendet und ist daher Startpunkt zu kopieren, wenn Sie eine Version dieser Datei für Ihr Gerät schreiben.

Hinweis:Möglicherweise wird hier die Meldung Kein Befehl angezeigt. Zum Umschalten halte die Ein/Aus-Taste gedrückt, während du auf die Lautertaste drückst. Wenn Ihre Geräte nicht drücken Sie lange auf eine beliebige Taste, um den Text umzuschalten.

device/yoyodyne/tardis/recovery/recovery_ui.cpp
#include <linux/input.h>

#include "common.h"
#include "device.h"
#include "screen_ui.h"

Header- und Elementfunktionen

Für die Geräteklasse sind Funktionen zur Rückgabe von Headern und Elementen erforderlich, die in den ausgeblendeten Elementen erscheinen. Wiederherstellungsmenü. Überschriften beschreiben die Bedienung des Menüs, d.h. Steuerelemente zum Ändern/Auswählen der markiertes Element) angezeigt.

static const char* HEADERS[] = { "Volume up/down to move highlight;",
                                 "power button to select.",
                                 "",
                                 NULL };

static const char* ITEMS[] =  {"reboot system now",
                               "apply update from ADB",
                               "wipe data/factory reset",
                               "wipe cache partition",
                               NULL };

Hinweis:Lange Zeilen werden abgeschnitten (nicht umgebrochen). Behalten Sie daher die Breite der Gerätebildschirms zu berücksichtigen.

CheckKey anpassen

Definieren Sie als Nächstes die RecoveryUI-Implementierung Ihres Geräts. In diesem Beispiel wird davon ausgegangen, tardis-Gerät verfügt über einen Bildschirm, sodass Sie die Einstellungen vom integrierten ScreenRecoveryUIImplement (siehe Anweisungen für Geräte ohne Bildschirm. Die einzige Funktion, mit der Sie von ScreenRecoveryUI anpassen ist CheckKey(), wodurch die anfängliche asynchrone Schlüsselverwaltung:

class TardisUI : public ScreenRecoveryUI {
  public:
    virtual KeyAction CheckKey(int key) {
        if (key == KEY_HOME) {
            return TOGGLE;
        }
        return ENQUEUE;
    }
};

KEY-Konstanten

Die KEY_*-Konstanten sind in linux/input.h definiert. CheckKey() ist wird aufgerufen, unabhängig davon, was während der Wiederherstellung vor sich geht: eingeschaltet ist, während der Paketinstallation, beim Löschen von Nutzerdaten usw. Es kann eine von vier Konstanten:

  • WECHSELN: Anzeige des Menüs und/oder des Textprotokolls ein- oder ausschalten
  • NEU BOOTEN. Gerät sofort neu starten
  • IGNORIEREN: Diesen Tastendruck ignorieren
  • ENQUEUE sein. Diesen Tastendruck synchron (d.h. von der Wiederherstellung) in die Warteschlange stellen Menüsystem bei aktiviertem Display)

CheckKey() wird jedes Mal aufgerufen, wenn auf ein Key-Down-Ereignis ein Key-up-Ereignis für denselben Schlüssel ein. (Die Abfolge der Ereignisse A-Ab-nach-B-nach-B--Auf-oben-Ergebnis ergibt nur CheckKey(B) wird angerufen.) CheckKey() kann anrufen IsKeyPressed(), um zu prüfen, ob andere Tasten gedrückt werden. (Im obigen Beispiel Abfolge von Schlüsselereignissen, wenn mit CheckKey(B) IsKeyPressed(A) aufgerufen wird hätte „true“ zurückgegeben.

CheckKey() kann den Status in seiner Klasse beibehalten. kann es nützlich sein, Tastensequenzen. Dieses Beispiel zeigt eine etwas komplexere Einrichtung: Das Display wird durch die Ein/Aus-Taste gedrückt halten und die Lautertaste drücken. Das Gerät kann dann sofort neu gestartet werden, indem Drücken der Ein/Aus-Taste fünfmal hintereinander (ohne andere Tasten dazwischen):

class TardisUI : public ScreenRecoveryUI {
  private:
    int consecutive_power_keys;

  public:
    TardisUI() : consecutive_power_keys(0) {}

    virtual KeyAction CheckKey(int key) {
        if (IsKeyPressed(KEY_POWER) && key == KEY_VOLUMEUP) {
            return TOGGLE;
        }
        if (key == KEY_POWER) {
            ++consecutive_power_keys;
            if (consecutive_power_keys >= 5) {
                return REBOOT;
            }
        } else {
            consecutive_power_keys = 0;
        }
        return ENQUEUE;
    }
};

Benutzeroberfläche zur Bildschirmwiederherstellung

Bei Verwendung eigener Bilder (Fehlersymbol, Installationsanimation, Fortschrittsanzeige) mit ScreenRecoveryUI nutzt die Variable animation_fps, um die Geschwindigkeit in Bilder pro Sekunde (fps) von Animationen.

Hinweis: Mit dem aktuellen interlace-frames.py-Script können Sie Folgendes tun: animation_fps-Informationen im Bild selbst speichern. In früheren Versionen von Android musste animation_fps selbst festlegen.

Um die Variable animation_fps festzulegen, überschreiben Sie ScreenRecoveryUI::Init()-Funktion in Ihrer abgeleiteten Klasse. Legen Sie den Wert fest und rufen Sie dann die Methode parent Init() , um die Initialisierung abzuschließen. Der Standardwert (20 fps) entspricht den Standard-Wiederherstellungs-Images; wenn Sie solche Bilder verwenden, Eine Init()-Funktion. Weitere Informationen zu Bildern finden Sie unter Images der Benutzeroberfläche für die Wiederherstellung.

Geräteklasse

Nachdem Sie über eine RecoveryUI-Implementierung verfügen, definieren Sie Ihre Geräteklasse (untergeordnete Klasse aus der integrierte Geräteklasse). Sie sollte eine einzelne Instanz Ihrer UI-Klasse erstellen und diese aus der Funktion GetUI():

class TardisDevice : public Device {
  private:
    TardisUI* ui;

  public:
    TardisDevice() :
        ui(new TardisUI) {
    }

    RecoveryUI* GetUI() { return ui; }

Wiederherstellung starten

Die Methode StartRecovery() wird zu Beginn der Wiederherstellung aufgerufen, nachdem die UI initialisiert wurde und nach dem Parsen der Argumente, aber bevor eine Aktion durchgeführt wurde bereits vergeben sind. Die Standardimplementierung hat keine Auswirkungen. Sie müssen dies also nicht in Ihrem ab, wenn Sie nichts zu tun haben:

   void StartRecovery() {
       // ... do something tardis-specific here, if needed ....
    }

Wiederherstellungsmenü bereitstellen und verwalten

Das System ruft zwei Methoden auf, um die Liste der Kopfzeilen und die Liste der Elemente abzurufen. In dieser -Implementierung gibt sie die statischen Arrays zurück, die am Anfang der Datei definiert sind:

const char* const* GetMenuHeaders() { return HEADERS; }
const char* const* GetMenuItems() { return ITEMS; }

HandleMenuKey

Stellen Sie als Nächstes eine HandleMenuKey()-Funktion bereit, die einen Tastendruck und die aktuelle die Sichtbarkeit des Menüs und entscheidet, welche Aktion ausgeführt werden soll:

   int HandleMenuKey(int key, int visible) {
        if (visible) {
            switch (key) {
              case KEY_VOLUMEDOWN: return kHighlightDown;
              case KEY_VOLUMEUP:   return kHighlightUp;
              case KEY_POWER:      return kInvokeItem;
            }
        }
        return kNoAction;
    }

Die -Methode verwendet einen Schlüsselcode, der zuvor vom CheckKey()-Methode des UI-Objekts) und den aktuellen Status des Menü-/Textprotokolls. Sichtbarkeit. Der Rückgabewert ist eine Ganzzahl. Ist der Wert 0 oder höher, wird dies als Position eines Menüelements, das sofort aufgerufen wird (siehe InvokeMenuItem()-Methode unten). Andernfalls kann es sich um einen der folgenden Werte handeln: vordefinierte Konstanten:

  • kHighlightUp: Menühighlight zum vorherigen Element verschieben
  • kHighlightDown: Menühighlight zum nächsten Element verschieben
  • kInvokeItem Aktuell markiertes Element aufrufen
  • kNoAction angeben. Keine Aktion mit diesem Tastendruck

Wie durch das Argument „visible“ impliziert, wird HandleMenuKey() aufgerufen, auch wenn das Menü nicht sichtbar. Im Gegensatz zu CheckKey() wird es während der Wiederherstellung nicht aufgerufen wie das Löschen von Daten oder das Installieren eines Pakets. und auf Eingaben warten.

Trackball-Mechanismen

Verfügt Ihr Gerät über einen Trackball-ähnlichen Eingabemechanismus (generiert Eingabeereignisse vom Typ EV_REL) und den Code REL_Y) generiert die Wiederherstellung die Tasten KEY_UP und KEY_DOWN, sobald die Das trackballähnliche Eingabegerät meldet die Bewegung auf der Y-Achse. Sie müssen lediglich KEY_UP und KEY_DOWN-Ereignisse für Menüaktionen verwenden. Diese Zuordnung erfolgt nicht für CheckKey(). Daher können Sie Trackball-Bewegungen nicht als Auslöser für einen Neustart oder um den Bildschirm umzuschalten.

Modifikatortasten

Rufe die IsKeyPressed() -Methode auf, um zu prüfen, ob Tasten als Modifikator gedrückt gehalten werden. Ihres eigenen UI-Objekts. Auf einigen Geräten wird z. B. durch Drücken von Alt+W bei der Wiederherstellung die Datenlöschung, unabhängig davon, ob das Menü sichtbar war oder nicht. Sie könnten Folgendes implementieren:

   int HandleMenuKey(int key, int visible) {
        if (ui->IsKeyPressed(KEY_LEFTALT) && key == KEY_W) {
            return 2;  // position of the "wipe data" item in the menu
        }
        ...
    }

Hinweis: Falls visible auf „false“ gesetzt ist, ist es nicht sinnvoll, die speziellen Werte, die das Menü manipulieren (Hervorhebung verschieben, hervorgehobenes Element aufrufen), da der Nutzer keine sehen Sie das Highlight. Sie können die Werte jedoch bei Bedarf zurückgeben.

InvokeMenuItem

Stellen Sie als Nächstes eine InvokeMenuItem()-Methode bereit, die ganzzahlige Positionen im Array zuordnet. von Artikeln, die von GetMenuItems() an Aktionen zurückgegeben wurden. Für das Array der Elemente im Tardis-Beispiel, verwenden Sie:

   BuiltinAction InvokeMenuItem(int menu_position) {
        switch (menu_position) {
          case 0: return REBOOT;
          case 1: return APPLY_ADB_SIDELOAD;
          case 2: return WIPE_DATA;
          case 3: return WIPE_CACHE;
          default: return NO_ACTION;
        }
    }

Diese Methode kann jedes Mitglied des enum-Werts "BuiltinAction" zurückgeben, um das System anzuweisen, Aktion (oder das Mitglied NO_ACTION, wenn das System nichts tun soll). Hier können Sie bieten zusätzliche Wiederherstellungsfunktionen, die über den Inhalt des Systems hinausgehen: Fügen Sie ein Element dafür hinzu. hier einfügen, hier ausführen, wenn dieser Menüpunkt aufgerufen wird, und NO_ACTION zurückgeben, damit das System sonst nichts.

„BuiltinAction“ enthält die folgenden Werte:

  • NO_ACTION: Nichts unternehmen.
  • NEU BOOTEN. Beenden Sie die Wiederherstellung und starten Sie das Gerät normal neu.
  • APPLY_EXT, APPLY_CACHE, APPLY_ADB_SIDELOAD anwenden. Installieren Sie ein Update-Paket aus verschiedenen an unterschiedlichen Orten. Weitere Informationen finden Sie unter Sideloading.
  • WIPE_CACHE ein. Formatieren Sie nur die Cache-Partition neu. Keine Bestätigung erforderlich, da relativ harmlos.
  • WIPE_DATA zurück. Die Benutzerdaten neu formatieren und Partitionen im Cache speichern (auch bekannt als Factory Data) zurückgesetzt werden. Der Nutzer wird aufgefordert, diese Aktion zu bestätigen, bevor er fortfahren kann.

Die letzte Methode, WipeData(), ist optional und wird aufgerufen, wenn eine Datenlöschung durchgeführt wird. eingeleitet wird (entweder bei der Wiederherstellung über das Menü oder wenn der Nutzer auf die Werkseinstellungen über das Hauptsystem zurücksetzen). Diese Methode wird vor den Nutzerdaten und dem Cache aufgerufen werden alle Partitionen gelöscht. Wenn auf Ihrem Gerät Nutzerdaten an einem anderen Ort als diesen beiden gespeichert werden sollten Sie sie hier löschen. Sie sollten 0 zurückgeben, um eine erfolgreiche Aktion anzuzeigen, und eine weitere für den Fehler zurückgegeben, obwohl der Rückgabewert derzeit ignoriert wird. Nutzerdaten und Cache werden alle Partitionen gelöscht, unabhängig davon, ob der Vorgang erfolgreich war.

   int WipeData() {
       // ... do something tardis-specific here, if needed ....
       return 0;
    }

Gerät festlegen

Fügen Sie abschließend Textbausteine am Ende der Datei „recovery_ui.cpp“ für den make_device()-Funktion, die eine Instanz Ihrer Geräteklasse erstellt und zurückgibt:

class TardisDevice : public Device {
   // ... all the above methods ...
};

Device* make_device() {
    return new TardisDevice();
}

Nachdem Sie die Datei „recovery_ui.cpp“ fertiggestellt haben, erstellen Sie sie und verknüpfen Sie sie mit der Wiederherstellung auf Ihrem Gerät. In Erstellen Sie unter Android.mk eine statische Bibliothek, die nur diese C++-Datei enthält:

device/yoyodyne/tardis/recovery/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += bootable/recovery
LOCAL_SRC_FILES := recovery_ui.cpp

# should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk
LOCAL_MODULE := librecovery_ui_tardis

include $(BUILD_STATIC_LIBRARY)

Geben Sie dann in der Board-Konfiguration für dieses Gerät Ihre statische Bibliothek als Wert von TARGET_RECOVERY_UI_LIB.

device/yoyodyne/tardis/BoardConfig.mk
 [...]

# device-specific extensions to the recovery UI
TARGET_RECOVERY_UI_LIB := librecovery_ui_tardis

UI-Images für die Wiederherstellung

Die Benutzeroberfläche für die Wiederherstellung besteht aus Images. Im Idealfall interagieren Nutzende nie mit der Benutzeroberfläche: Während eines normalen Updates startet das Smartphone bei der Wiederherstellung und füllt die Fortschrittsanzeige der Installation aus. und startet das neue System ohne Eingabe des Nutzers. Im Falle eines Update-Problem besteht, besteht die einzige Nutzeraktion, die durchgeführt werden kann, darin, den Kundendienst anzurufen.

Eine reine Image-Schnittstelle macht eine Lokalisierung überflüssig. Ab Android 5.0 Bei einem Update kann neben dem Bild auch eine Textzeichenfolge wie „Systemupdate wird installiert...“ angezeigt werden. Weitere Informationen finden Sie unter Lokalisierter Wiederherstellungstext.

Android 5.0 und höher

Die Wiederherstellungs-UI unter Android 5.0 und höher verwendet zwei Haupt-Images: das error-Image. und der Animation Installation.

Bild wird während des OTA-Fehlers angezeigt

Abbildung 1: icon_error.png

Bild, das während der OTA-Installation angezeigt wird

Abbildung 2. icon_installing.png

Die Installationsanimation wird als einzelnes PNG-Bild mit verschiedenen Frames des Animation mit Zeilensprüngen (wodurch erscheint Abbildung 2 zerdrückt). Beispiel: Für eine 7-Frame-Animation im Format 200 x 200, erstellen Sie ein einzelnes Bild mit 200 x 1400 Pixel, wobei der erste Frame die Zeilen 0, 7, 14, 21, ...; der zweite Frame die Zeilen 1, 8, 15, 22, ...; Das kombinierte Bild enthält ein Text-Chunk, der die Anzahl der Animationsframes und die Anzahl der Frames pro Sekunde angibt (fps) Das Tool bootable/recovery/interlace-frames.py verwendet eine Reihe von Eingabeframes und kombiniert sie zu dem erforderlichen zusammengesetzten Image, das für die Wiederherstellung verwendet wird.

Standardbilder sind in verschiedenen Dichten verfügbar und befinden sich bootable/recovery/res-$DENSITY/images (z.B. bootable/recovery/res-hdpi/images. Um während der Installation ein statisches Image zu verwenden, müssen Sie nur das Bild icon_installing.png bereitstellen und die Anzahl der Frames Animation auf 0 (das Fehlersymbol ist nicht animiert, es ist immer ein statisches Bild).

Android 4.x und niedriger

Die Wiederherstellungs-UI unter Android 4.x und niedriger verwendet das error-Abbild (siehe oben) und den Installation einer Animation und mehrerer Overlay-Bilder:

Bild, das während der OTA-Installation angezeigt wird

Abbildung 3. icon_installing.png

Bild wird als erstes angezeigt
Overlay

Abbildung 4. icon-installing_overlay01.png

Bild wird als 7. angezeigt
Overlay

Abbildung 5. icon_installing_overlay07.png

Während der Installation wird der Bildschirminhalt durch Zeichnen der Datei icon_installing.png erstellt. Bild und dann einen der Overlay-Frames mit dem entsprechenden Versatz darüber zeichnen. Hier ist eine rote wird überlagert, um die Position des Overlays über dem Basisbild hervorzuheben:

zusammengesetztes Bild von
Overlay für Installation plus erstes Overlay

Abbildung 6: Animationsframe 1 wird installiert (icon_installing.png + icon_installing_overlay01.png)

zusammengesetztes Bild von
Installation plus siebtes Overlay

Abbildung 7: Animationsframe 7 wird installiert (icon_installing.png + icon_installing_overlay07.png)

Die nachfolgenden Frames werden angezeigt, indem nur das nächste Overlay-Bild darüber gezeichnet wird. bereits vorhanden; wird das Basis-Image nicht neu gezeichnet.

Die Anzahl der Frames in der Animation, die gewünschte Geschwindigkeit sowie x- und y-Offsets des Overlays relativ zur Basis durch Mitgliedsvariablen der ScreenRecoveryUI-Klasse festgelegt werden. Bei Verwendung statt Standard-Images verwenden, überschreiben Sie die Init()-Methode in können Sie diese Werte für Ihre benutzerdefinierten Images ändern (Details finden Sie unter ScreenRecoveryUI). Das Skript bootable/recovery/make-overlay.py kann beim Konvertieren einer Reihe von Bildframes helfen den Wert „Basisbild + Overlay-Bilder“ die für die Wiederherstellung benötigt werden, einschließlich der Berechnung der notwendige Offsets.

Die Standardbilder befinden sich in bootable/recovery/res/images. Statisches Bild verwenden Während der Installation müssen Sie nur das Image "icon_installing.png" bereitstellen und die Anzahl der Frames in der Animation auf 0 setzen (das Fehlersymbol ist nicht animiert, es ist immer ein statisches Bild).

Lokalisierter Wiederherstellungstext

Android 5.x zeigt eine Textzeichenfolge (z.B. „Systemupdate wird installiert...“. Bild. Wenn das Hauptsystem bei der Wiederherstellung startet, wird die aktuelle Sprache des Nutzers als Befehlszeilenoption zur Wiederherstellung. Für jede anzuzeigende Nachricht umfasst die Wiederherstellung zusammengesetztes Bild mit vorab gerenderten Textzeichenfolgen für diese Nachricht in jeder Sprache.

Beispielbild für Wiederherstellungstextstrings:

Bild des Wiederherstellungstexts

Abbildung 8: Lokalisierter Text für Wiederherstellungsnachrichten

Im Wiederherstellungstext können die folgenden Meldungen angezeigt werden:

  • Systemupdate wird installiert...
  • Fehler!
  • Wird gelöscht... (beim Löschen der Daten auf die Werkseinstellungen)
  • Kein Befehl (wenn ein Nutzer manuell in die Wiederherstellung startet)

Die Android-App in bootable/recovery/tools/recovery_l10n/ rendert Lokalisierungen einer Nachricht und erstellt das zusammengesetzte Bild. Weitere Informationen zur Verwendung dieser App findest du in der Kommentare in bootable/recovery/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java

Wenn ein Nutzer die Wiederherstellung manuell startet, ist die Sprache möglicherweise nicht verfügbar und es wird kein Text angezeigt. angezeigt. Verwenden Sie die SMS nicht als kritische Nachricht für den Wiederherstellungsprozess.

Hinweis: Die ausgeblendete Oberfläche, auf der Protokollmeldungen angezeigt werden und Nutzer die folgenden Aktionen ausführen können: Auswahlaktionen aus dem Menü sind nur auf Englisch verfügbar.

Fortschrittsanzeigen

Fortschrittsbalken können unter dem Hauptbild (oder der Animation) angezeigt werden. Der Fortschrittsbalken wird erstellt, Kombinieren von zwei Eingabebildern, die dieselbe Größe haben müssen:

Leerer Fortschrittsbalken

Abbildung 9. progress_empty.png

vollständige Fortschrittsanzeige

Abbildung 10. progress_fill.png

Das linke Ende des fill-Bildes wird neben dem leeres Bild, um die Fortschrittsanzeige einzublenden. Die Position der Grenze zwischen den beiden Bilder den Fortschritt anzeigen. Mit den obigen Paaren von Eingabebildern Anzeige:

Fortschrittsanzeige bei 1%

Abbildung 11. Fortschrittsanzeige bei 1 %

Fortschrittsanzeige bei 10%

Abbildung 12. Fortschrittsanzeige bei 10%

Fortschrittsanzeige bei 50%

Abbildung 13. Fortschrittsanzeige bei 50%

Sie können gerätespezifische Versionen dieser Bilder bereitstellen, indem Sie sie in (in dieser Beispiel) device/yoyodyne/tardis/recovery/res/images . Die Dateinamen müssen mit den oben aufgeführten übereinstimmen. eine Datei in diesem Verzeichnis gefunden wird, verwendet das Build-System diese anstelle des entsprechenden Standard-Images. Nur PNGs im RGB- oder Das RGBA-Format mit einer Farbtiefe von 8 Bit wird unterstützt.

Hinweis: Wenn unter Android 5.x die Sprache für die Wiederherstellung bekannt ist und Rechts-nach-links-Sprache (Arabisch, Hebräisch usw.) angezeigt wird, füllt sich die Fortschrittsanzeige von rechts nach hat den Chat verlassen.

Geräte ohne Bildschirme

Nicht alle Android-Geräte haben ein Display. Wenn es sich bei Ihrem Gerät um ein monitorloses Gerät handelt oder Audio-UI verwenden, müssen Sie die Wiederherstellungs-UI möglicherweise umfassender anpassen. Stattdessen zur Erstellung einer abgeleiteten Klasse von ScreenRecoveryUI, erstellen Sie eine direkte Unterklasse der übergeordneten Klasse "RecoveryUI".

RecoveryUI bietet Methoden zur Verarbeitung untergeordneter UI-Vorgänge wie „aktualisiere die Fortschrittsanzeige“, „Zeig mir das Menü“ „Menüauswahl ändern“, und so weiter. Sie können die um eine geeignete Schnittstelle für Ihr Gerät bereitzustellen. Vielleicht hat Ihr Gerät LEDs, können Sie verschiedene Farben oder Blinkmuster verwenden, um den Zustand anzuzeigen, oder Sie können Audio. Vielleicht möchten Sie ein Menü oder den "Textanzeige"-Modus überhaupt nicht unterstützen. Sie können den Zugriff über CheckKey() und HandleMenuKey()-Implementierungen, bei denen nie die Anzeige ein- oder ausgeschaltet wird ein. In diesem Fall können viele der erforderlichen RecoveryUI-Methoden leer sein. Stubs.)

Unter bootable/recovery/ui.h finden Sie die Deklaration von RecoveryUI. Dort erfahren Sie, welche Methoden Sie verwenden. die Sie unterstützen müssen. RecoveryUI ist abstrakt – einige Methoden sind rein virtuell und müssen von abgeleiteten Klassen erstellt, enthält aber den Code für die Verarbeitung der wichtigsten Eingaben. Sie können das überschreiben, wenn Ihr Gerät keine Schlüssel hat oder Sie sie anders verarbeiten möchten.

Updater

Sie können in der Installation des Update-Pakets gerätespezifischen Code verwenden, indem Sie Ihre eigene Erweiterungsfunktionen, die in Ihrem Updater-Skript aufgerufen werden können. Hier ein Beispiel für das Tardis-Gerät:

device/yoyodyne/tardis/recovery/recovery_updater.c
#include <stdlib.h>
#include <string.h>

#include "edify/expr.h"

Jede Erweiterungsfunktion hat dieselbe Signatur. Die Argumente sind der Name, unter dem der -Funktion, ein State*-Cookie, die Anzahl der eingehenden Argumente und ein Array von Expr*-Zeigern, die die Argumente darstellen. Der Rückgabewert ist ein neu zugewiesene Value*.

Value* ReprogramTardisFn(const char* name, State* state, int argc, Expr* argv[]) {
    if (argc != 2) {
        return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
    }

Ihre Argumente wurden zum Zeitpunkt des Funktionsaufrufs nicht ausgewertet – die welche von ihnen ausgewertet werden und wie oft. Daher können Sie Erweiterungen verwenden, können Sie Ihre eigenen Kontrollstrukturen implementieren. Call Evaluate() zum Auswerten Ein Expr* -Argument, das ein Value* zurückgibt. Wenn Evaluate() gibt NULL zurück, sollten Sie alle Ressourcen freigeben, die Sie halten, und sofort NULL zurückgeben (dies bricht den Edify-Stack ab). Andernfalls übernehmen Sie die Eigentumsrechte für den zurückgegebenen Wert und sind dafür verantwortlich, FreeValue().

Angenommen, die Funktion benötigt zwei Argumente: einen Schlüssel mit Stringwert und einen mit einem Blobwert. image an. Sie könnten Argumente wie folgt lesen:

   Value* key = EvaluateValue(state, argv[0]);
    if (key == NULL) {
        return NULL;
    }
    if (key->type != VAL_STRING) {
        ErrorAbort(state, "first arg to %s() must be string", name);
        FreeValue(key);
        return NULL;
    }
    Value* image = EvaluateValue(state, argv[1]);
    if (image == NULL) {
        FreeValue(key);    // must always free Value objects
        return NULL;
    }
    if (image->type != VAL_BLOB) {
        ErrorAbort(state, "second arg to %s() must be blob", name);
        FreeValue(key);
        FreeValue(image)
        return NULL;
    }

Die Suche auf NULL und das Freigeben zuvor ausgewerteter Argumente kann bei mehreren Argumente. Die Funktion ReadValueArgs() kann Ihnen dabei helfen. Anstelle des Codes hätten Sie Folgendes schreiben können:

   Value* key;
    Value* image;
    if (ReadValueArgs(state, argv, 2, &key, &image) != 0) {
        return NULL;     // ReadValueArgs() will have set the error message
    }
    if (key->type != VAL_STRING || image->type != VAL_BLOB) {
        ErrorAbort(state, "arguments to %s() have wrong type", name);
        FreeValue(key);
        FreeValue(image)
        return NULL;
    }

ReadValueArgs() führt keine Typprüfung durch, daher müssen Sie dies hier tun: es ist mehr dies mit einer if-Anweisung zu tun, auf die Kosten einer etwas geringeren wenn er fehlschlägt. Aber ReadValueArgs() übernimmt die Auswertung Argumenten erstellen und alle zuvor bewerteten Argumente freigeben (sowie ein nützliches Fehlermeldung angezeigt wird, wenn eine der Bewertungen fehlschlägt. Sie können einen ReadValueVarArgs()-Funktion zum Auswerten einer variablen Anzahl von Argumente. Sie gibt ein Array von Value* zurück.

Nachdem Sie die Argumente ausgewertet haben, führen Sie die Arbeit der Funktion aus:

   // key->data is a NUL-terminated string
    // image->data and image->size define a block of binary data
    //
    // ... some device-specific magic here to
    // reprogram the tardis using those two values ...

Der Rückgabewert muss ein Value*-Objekt sein. die Eigentümerschaft dieses Objekts an für den Anrufer. Der Aufrufer übernimmt die Eigentümerschaft für alle Daten, auf die dieses Value*, insbesondere das Datenelement.

In diesem Fall möchten Sie einen true- oder false-Wert zurückgeben, um den Erfolg anzuzeigen. Denken Sie an die Konvention, dass der leere String false und alle anderen Strings true sind. Ich muss ein Wertobjekt mit einer "maloc'd"-Kopie der konstanten Zeichenfolge angeben, die zurückgegeben werden soll, da das Objekt free() wird beide. Vergessen Sie nicht, FreeValue() anzurufen in der die Sie durch Auswertung Ihrer Argumente erhalten haben.

   FreeValue(key);
    FreeValue(image);

    Value* result = malloc(sizeof(Value));
    result->type = VAL_STRING;
    result->data = strdup(successful ? "t" : "");
    result->size = strlen(result->data);
    return result;
}

Die Convenience-Funktion StringValue() verpackt einen String in ein neues Wertobjekt. Verwenden Sie , um den obigen Code kürzer zu formulieren:

   FreeValue(key);
    FreeValue(image);

    return StringValue(strdup(successful ? "t" : ""));
}

Um Funktionen mit dem edify-Interpreter zu verknüpfen, geben Sie die Funktion Register_foo, wobei foo der Name der statischen Bibliothek ist, die Folgendes enthält: diesem Code. Rufen Sie RegisterFunction() auf, um jede Erweiterungsfunktion zu registrieren. Von der Konvention sollten gerätespezifische Funktionen device.whatever verwendet werden, um sie zu vermeiden. Konflikte mit zukünftig hinzugefügten integrierten Funktionen besteht.

void Register_librecovery_updater_tardis() {
    RegisterFunction("tardis.reprogram", ReprogramTardisFn);
}

Sie können das Makefile jetzt so konfigurieren, dass mit Ihrem Code eine statische Bibliothek erstellt wird. (Das gleiche Makefile, mit dem die Wiederherstellungs-UI im vorherigen Abschnitt angepasst wurde hat Ihr Gerät möglicherweise statische Bibliotheken definiert sind.)

device/yoyodyne/tardis/recovery/Android.mk
include $(CLEAR_VARS)
LOCAL_SRC_FILES := recovery_updater.c
LOCAL_C_INCLUDES += bootable/recovery

Der Name der statischen Bibliothek muss mit dem Namen des Register_libname-Funktion enthalten.

LOCAL_MODULE := librecovery_updater_tardis
include $(BUILD_STATIC_LIBRARY)

Konfigurieren Sie schließlich den Wiederherstellungs-Build, um Ihre Bibliothek abzurufen. Mediathek hinzufügen zu TARGET_RECOVERY_UPDATER_LIBS (kann mehrere Bibliotheken enthalten; alle werden registriert). Wenn Ihr Code von anderen statischen Bibliotheken abhängt, die selbst keine Erweiterungen sind (z.B. keine Register_libname-Funktion haben), können Sie diese in TARGET_RECOVERY_UPDATER_EXTRA_LIBS, um ihn mit dem Updater zu verknüpfen, ohne den (nicht vorhandene) Registrierungsfunktion. Wenn Sie mit Ihrem gerätespezifischen Code z. B. zlib zum Dekomprimieren von Daten verwenden, fügen Sie hier libz ein.

device/yoyodyne/tardis/BoardConfig.mk
 [...]

# add device-specific extensions to the updater binary
TARGET_RECOVERY_UPDATER_LIBS += librecovery_updater_tardis
TARGET_RECOVERY_UPDATER_EXTRA_LIBS +=

Die Updater-Skripts in deinem OTA-Paket können deine Funktion jetzt wie jede andere aufrufen. Um neu zu programmieren Ihrem Tardis-Gerät enthält, kann das Update-Skript Folgendes enthalten: tardis.reprogram("the-key", package_extract_file("tardis-image.dat")) Hierbei wird der Version mit einem Argument der integrierten Funktion package_extract_file() gibt den Inhalt einer Datei zurück, die aus dem Update-Paket extrahiert wurde, als Blob zur Erstellung das zweite Argument für die neue Erweiterungsfunktion.

OTA-Paketerstellung

Der letzte Schritt besteht darin, die Tools zur OTA-Paketgenerierung über eure gerätespezifische Daten und Ausgabe-Updater-Skripte, die Aufrufe Ihrer Erweiterungsfunktionen enthalten.

Zuerst muss das Build-System von einem gerätespezifischen Daten-BLOB erfahren. Annahme Ihrer Daten Datei befindet sich in device/yoyodyne/tardis/tardis.dat, deklarieren Sie Folgendes in Ihrer AndroidBoard.mk des Geräts:

device/yoyodyne/tardis/AndroidBoard.mk
  [...]

$(call add-radio-file,tardis.dat)

Sie können sie auch in einer Android.mk-Datei speichern, dann muss sie dann aber von einem Gerät geschützt werden. da alle Android.mk-Dateien im Baum unabhängig vom Gerät geladen werden. entwickelt. Wenn Ihre Baumstruktur mehrere Geräte enthält, soll die Datei tardis.dat nur hinzugefügt werden, wenn Erstellen des Tardis-Geräts)

device/yoyodyne/tardis/Android.mk
  [...]

# an alternative to specifying it in AndroidBoard.mk
ifeq (($TARGET_DEVICE),tardis)
  $(call add-radio-file,tardis.dat)
endif

Aus historischen Gründen werden diese Dateien als Optionsfelder bezeichnet. haben sie vielleicht nichts mit Geräteradio (falls vorhanden). Sie sind einfach undurchsichtige Daten-Blobs, in die das Build-System kopiert Die von den OTA-Generierungstools verwendeten ZIP-Dateien mit Zieldateien. Beim Erstellen eines Builds ist tardis.dat in der Datei target-files.zip als RADIO/tardis.dat gespeichert. Sie können add-radio-file, um beliebig viele Dateien hinzuzufügen.

Python-Modul

Schreiben Sie zum Erweitern der Releasetools ein Python-Modul (muss den Namen „releasetools.py“) tragen. aufrufen können, falls vorhanden. Beispiel:

device/yoyodyne/tardis/releasetools.py
import common

def FullOTA_InstallEnd(info):
  # copy the data into the package.
  tardis_dat = info.input_zip.read("RADIO/tardis.dat")
  common.ZipWriteStr(info.output_zip, "tardis.dat", tardis_dat)

  # emit the script code to install this data on the device
  info.script.AppendExtra(
      """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")

Eine separate Funktion übernimmt die Generierung eines inkrementellen OTA-Pakets. In diesem Fall Angenommen, Sie müssen die Tardis-Datei nur dann neu programmieren, wenn sich die Datei tardis.dat geändert hat. zwischen zwei Builds.

def IncrementalOTA_InstallEnd(info):
  # copy the data into the package.
  source_tardis_dat = info.source_zip.read("RADIO/tardis.dat")
  target_tardis_dat = info.target_zip.read("RADIO/tardis.dat")

  if source_tardis_dat == target_tardis_dat:
      # tardis.dat is unchanged from previous build; no
      # need to reprogram it
      return

  # include the new tardis.dat in the OTA package
  common.ZipWriteStr(info.output_zip, "tardis.dat", target_tardis_dat)

  # emit the script code to install this data on the device
  info.script.AppendExtra(
      """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")

Modulfunktionen

Sie können im -Modul die folgenden Funktionen bereitstellen (nur diejenigen implementieren, die Sie benötigen).

FullOTA_Assertions()
Wird kurz vor Beginn der Generierung eines vollständigen OTA-Updates aufgerufen. Hier können Sie Assertions ausgeben über den aktuellen Status des Geräts. Geben Sie keine Skriptbefehle aus, durch die Änderungen am .
FullOTA_InstallBegin()
Wird aufgerufen, nachdem alle Assertions zum Gerätestatus vorbei sind, aber vor Änderungen gemacht wurden. Sie können Befehle für gerätespezifische Updates ausgeben, die vor dem alles andere auf dem Gerät geändert wurde.
FullOTA_InstallEnd()
Wird am Ende der Skriptgenerierung nach den Skriptbefehlen zum Aktualisieren des Boot- und Systempartitionen ausgegeben wurden. Sie können auch zusätzliche Befehle für gerätespezifische Updates.
IncrementalOTA_Assertions()
Ähnlich wie FullOTA_Assertions(), wird aber beim Generieren einer inkrementellen Update-Paket.
IncrementalOTA_VerifyBegin()
Wird aufgerufen, nachdem alle Assertions zum Gerätestatus vorbei sind, aber bevor Änderungen gemacht wurden. Sie können Befehle für gerätespezifische Updates ausgeben, die vor der Ausführung von Updates ausgeführt werden müssen. auf dem Gerät geändert.
IncrementalOTA_VerifyEnd()
Wird am Ende der Überprüfungsphase aufgerufen, wenn das Skript die Bestätigung der die es angetippt wird, den erwarteten Startinhalt haben. Zu diesem Zeitpunkt gibt es noch nichts Gerät geändert wurde. Sie können auch Code für zusätzliche gerätespezifische und Überprüfungen.
IncrementalOTA_InstallBegin()
Wird aufgerufen, nachdem die zu patchenden Dateien auf die erwartete Version geprüft wurden before (vorherige Änderungen) Sie können Befehle für gerätespezifische Updates, die ausgeführt werden müssen, bevor andere Änderungen auf dem Gerät vorgenommen wurden.
IncrementalOTA_InstallEnd()
Ähnlich wie beim vollständigen Gegenstück für das OTA-Paket wird dies am Ende des Skripts aufgerufen. nach der Aktualisierung der Boot- und Systempartitionen. ausgegeben. Sie können auch zusätzliche Befehle für gerätespezifische Updates ausgeben.

Hinweis:Wenn die Stromversorgung des Geräts unterbrochen wird, wird die OTA-Installation möglicherweise vom beginnen. Seien Sie darauf vorbereitet, mit Geräten vorzugehen, auf denen diese Befehle bereits ausgeführt wurden, vollständig oder teilweise.

Funktionen an Infoobjekte übergeben

Übergeben Sie Funktionen an ein einzelnes Informationsobjekt, das verschiedene nützliche Elemente enthält:

  • info.input_zip: (Nur vollständige OTAs) Das zipfile.ZipFile-Objekt für das .zip als Zieldateien eingeben.
  • info.source_zip. (Nur inkrementelle OTAs) Das zipfile.ZipFile -Objekt für Die ZIP-Datei mit den Quellzieldateien (der Build, der bereits auf dem Gerät vorhanden ist, wenn das inkrementelle Paket installiert wird).
  • info.target_zip (Nur inkrementelle OTAs) Das zipfile.ZipFile -Objekt für die Zieldateien im ZIP-Format (das inkrementelle Paket wird auf dem Gerät abgelegt)
  • info.output_zip: Paket wird erstellt; ein zipfile.ZipFile -Objekt geöffnet für das Schreiben. Verwenden Sie „common.ZipWriteStr(info.output_zip, filename, data)“ zum Hinzufügen eines in das Paket.
  • info.script Skriptobjekt, an das Sie Befehle anhängen können. Anruf info.script.AppendExtra(script_text), um Text in das Skript auszugeben. Achten Sie darauf, dass der Ausgabetext mit einem Semikolon endet, damit keine Befehle ausgegeben werden .

Details zum Objekt „info“ finden Sie in der Python Software Foundation-Dokumentation für ZIP-Archive

Modulstandort angeben

Geben Sie den Speicherort des Releasetools.py-Skripts Ihres Geräts in der Datei BoardConfig.mk an:

device/yoyodyne/tardis/BoardConfig.mk
 [...]

TARGET_RELEASETOOLS_EXTENSIONS := device/yoyodyne/tardis

Wenn TARGET_RELEASETOOLS_EXTENSIONS nicht festgelegt ist, wird standardmäßig die Verzeichnis $(TARGET_DEVICE_DIR)/../common (device/yoyodyne/common ) in diesem Beispiel). Es empfiehlt sich, den Speicherort des Skriptsreleasetools.py explizit zu definieren. Beim Erstellen des Tardis-Geräts ist das Skript „releasetools.py“ in den Zieldateien enthalten. ZIP-Datei (META/releasetools.py ).

Wenn Sie die Release-Tools ausführen (entweder img_from_target_files oder ota_from_target_files) dem Skript „releasetools.py“ in der ZIP-Datei „target-files“, wenn vorhanden ist, gegenüber derjenigen aus der Android-Quellstruktur. Sie können auch explizit den Pfad zu den gerätespezifischen Erweiterungen mit -s (oder --device_specific) angezeigt, die die höchste Priorität hat. So können Sie Fehler beheben, Änderungen an den Releasetools-Erweiterungen vornehmen und diese Änderungen auf alte Zieldateien.

Wenn Sie jetzt ota_from_target_files ausführen, wird automatisch gerätespezifisches Modul aus der ZIP-Datei „target_files“ und verwendet es bei der OTA-Generierung Pakete:

./build/make/tools/releasetools/ota_from_target_files \
    -i PREVIOUS-tardis-target_files.zip \
    dist_output/tardis-target_files.zip \
    incremental_ota_update.zip

Alternativ können Sie bei der Ausführung gerätespezifische Erweiterungen angeben. ota_from_target_files

./build/make/tools/releasetools/ota_from_target_files \
    -s device/yoyodyne/tardis \
    -i PREVIOUS-tardis-target_files.zip \
    dist_output/tardis-target_files.zip \
    incremental_ota_update.zip

Hinweis:Eine vollständige Liste der Optionen finden Sie in der ota_from_target_files Kommentare in build/make/tools/releasetools/ota_from_target_files.

Sideloading-Mechanismus

Die Wiederherstellung verfügt über einen Sideloading-Mechanismus zum manuellen Installieren eines Updatepakets ohne Over-the-Air über das Hauptsystem herunterladen. Sideloading ist nützlich für das Debugging auf Geräten, auf denen das Hauptsystem nicht gestartet werden kann.

Bisher wurden beim Sideloading Pakete von der SD-Karte des Geräts geladen. in Lässt sich das Gerät nicht starten, kann das Paket mit einem anderen Computer und dann die SD-Karte, die in das Gerät eingelegt ist. Für Android-Geräte ohne externe Wechseldatenträger, unterstützt die Wiederherstellung zwei weitere Mechanismen für das Sideloading: Pakete werden aus der Cache-Partition geladen und sie werden mit ADB über USB geladen.

Zum Aufrufen der einzelnen Sideload-Mechanismen muss die Device::InvokeMenuItem()-Methode deines Geräts verwendet werden kann die folgenden Werte von „BuiltinAction“ zurückgeben:

  • ANWENDEN_EXT. Update-Paket per Sideload aus dem externen Speicher ( /sdcard) übertragen -Verzeichnis). In „recovery.fstab“ muss der Bereitstellungspunkt /sdcard definiert werden. Dies ist nicht verwendbar auf Geräten, die eine SD-Karte mit einem Symlink zu /data (oder einigen ähnlichen Mechanismus). /data ist normalerweise nicht für die Wiederherstellung verfügbar, weil verschlüsselt sein. Auf der Benutzeroberfläche zur Wiederherstellung wird in /sdcard ein Menü mit ZIP-Dateien angezeigt. kann der Nutzer eine Option auswählen.
  • ANWENDEN_CACHE Ähnlich wie beim Laden eines Pakets aus /sdcard, mit der Ausnahme, dass Das Verzeichnis /cache (das immer für die Wiederherstellung verfügbar ist) wird verwendet . Im regulären System kann /cache nur von privilegierten Nutzern geschrieben werden. Wenn das Gerät nicht bootfähig ist, kann nicht in das Verzeichnis /cache geschrieben werden. wodurch dieser Mechanismus nur begrenzt nützlich ist.
  • APPLY_ADB_SIDELOAD festlegen. Ermöglicht dem Nutzer, über ein USB-Kabel ein Paket an das Gerät zu senden und das ADB-Entwicklungstool. Wenn dieser Mechanismus aufgerufen wird, startet die Wiederherstellung eine eigene Miniversion Version des adbd-Daemons, damit ADB auf einem verbundenen Hostcomputer mit ihm kommunizieren kann. Dieses Mini Version unterstützt nur einen Befehl: adb sideload filename. Die benannte Datei wird vom Hostcomputer an das Gerät gesendet, das dann installiert es genau wie im lokalen Speicher.

Einige Einschränkungen:

  • Es wird nur USB-Transport unterstützt.
  • Wenn bei der Wiederherstellung adbd normal ausgeführt wird (normalerweise bei UserDebug- und Eng-Builds „true“), wird heruntergefahren, während sich das Gerät im ADB-Sideload-Modus befindet und wird neu gestartet, wenn ADB Sideload hat ein Paket empfangen. Im ADB-Sideload-Modus werden keine ADB-Befehle als sideload ( logcat, reboot, push, pull, shell usw. schlagen fehl).
  • Sie können den ADB-Sideload-Modus auf dem Gerät nicht beenden. Zum Abbrechen können Sie /dev/null (oder etwas anderes, das kein gültiges Paket ist) als Paket und kann dies nicht bestätigt werden und der Installationsvorgang wird abgebrochen. Wiederherstellungs-UI wird die Methode CheckKey() der Implementierung für Tastendruck Sie können also eine Zeichenfolge bereitstellen, die das Gerät neu startet und im ADB-Sideload-Modus funktioniert.