Cihaza özel kod

Kurtarma sistemi, cihaza özel kod eklemek için çeşitli kancalar içerir, böylece OTA güncellemeleri, cihazın Android sistemi dışındaki kısımlarını da güncelleyebilir (örn. ana bant veya radyo işlemcisi).

Aşağıdaki bölümler ve örnekler, yoyodyne satıcısı tarafından üretilen tardis cihazını özelleştirir.

Bölme haritası

Android 2.3'ten itibaren platform, eMMc flash cihazlarını ve bu cihazlarda çalışan ext4 dosya sistemini destekler. Ayrıca Bellek Teknolojisi Aygıtı (MTD) flash aygıtlarını ve eski sürümlerden yaffs2 dosya sistemini de destekler.

Bölüm eşleme dosyası TARGET_RECOVERY_FSTAB tarafından belirtilir; bu dosya hem kurtarma ikili dosyası hem de paket oluşturma araçları tarafından kullanılır. BoardConfig.mk'de TARGET_RECOVERY_FSTAB içinde harita dosyasının adını belirtebilirsiniz.

Örnek bir bölüm haritası dosyası şöyle görünebilir:

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

İsteğe bağlı olan /sdcard haricinde, bu örnekteki tüm bağlama noktaları tanımlanmalıdır (aygıtlar ayrıca fazladan bölümler ekleyebilir). Desteklenen beş dosya sistemi türü vardır:

yaffs2
Bir MTD flash aygıtının üzerinde bir yaffs2 dosya sistemi. "cihaz", MTD bölümünün adı olmalı ve /proc/mtd içinde görünmelidir.
mtd
Önyükleme ve kurtarma gibi önyüklenebilir bölümler için kullanılan ham bir MTD bölümü. MTD aslında takılı değildir, ancak bağlama noktası, bölümü bulmak için bir anahtar olarak kullanılır. "cihaz" /proc/mtd içindeki MTD bölümünün adı olmalıdır.
ext4
Bir eMMc flash aygıtının üzerinde bir ext4 dosya sistemi. "cihaz" blok cihazın yolu olmalıdır.
emmc
Önyükleme ve kurtarma gibi önyüklenebilir bölümler için kullanılan ham bir eMMc blok aygıtı. mtd tipine benzer şekilde, eMMc hiçbir zaman gerçekte bağlanmaz, ancak tablodaki aygıtı bulmak için bağlama noktası dizesi kullanılır.
vfat
Tipik olarak bir SD kart gibi harici depolama için bir blok aygıtın üzerindeki bir FAT dosya sistemi. Cihaz blok cihazıdır; device2, birincil aygıtın montajı başarısız olursa sistemin bağlamaya çalıştığı ikinci bir blok aygıtıdır (bölüm tablosuyla biçimlendirilebilen veya biçimlendirilemeyen SD kartlarla uyumluluk için).

Tüm bölümler kök dizine bağlanmalıdır (yani bağlama noktası değeri eğik çizgi ile başlamalı ve başka eğik çizgi içermemelidir). Bu kısıtlama yalnızca kurtarma sırasında dosya sistemlerini bağlamak için geçerlidir; ana sistem bunları herhangi bir yere monte etmekte serbesttir. /boot , /recovery ve /misc dizinleri ham türler (mtd veya emmc), /system , /data , /cache ve /sdcard (varsa) dizinleri dosya sistemi türleri (yaffs2, ext4 veya vfat).

Android 3.0'dan başlayarak, recovery.fstab dosyası isteğe bağlı ek bir alan kazanır: options . Şu anda tanımlanmış tek seçenek, bölümün uzunluğunu açıkça belirtmenize izin veren uzunluktur . Bu uzunluk, bölümü yeniden biçimlendirirken kullanılır (örneğin, veri silme/fabrika ayarlarına sıfırlama işlemi sırasında kullanıcı verileri bölümü için veya tam bir OTA paketinin kurulumu sırasında sistem bölümü için). Uzunluk değeri negatifse, uzunluk değeri gerçek bölüm boyutuna eklenerek biçimlendirilecek boyut alınır. Örneğin, "uzunluk=-16384" ayarı, o bölümün son 16k'sının, o bölüm yeniden biçimlendirildiğinde üzerine yazılmaması anlamına gelir. Bu, kullanıcı verileri bölümünün şifrelenmesi gibi özellikleri destekler (burada şifreleme meta verileri, üzerine yazılmaması gereken bölümün sonunda depolanır).

Not: Cihaz2 ve seçenekler alanları isteğe bağlıdır ve ayrıştırmada belirsizlik yaratır. Satırdaki dördüncü alandaki giriş '/' karakteri ile başlıyorsa cihaz2 girişi olarak kabul edilir; giriş bir '/' karakteri ile başlamıyorsa, bir seçenekler alanı olarak kabul edilir.

Önyükleme animasyonu

Cihaz üreticileri, bir Android cihaz önyüklenirken gösterilen animasyonu özelleştirme olanağına sahiptir. Bunu yapmak için, bootanimation biçimindeki özelliklere göre düzenlenmiş ve yerleştirilmiş bir .zip dosyası oluşturun.

Android Things cihazları için, sıkıştırılmış dosyayı Android Things konsoluna yükleyerek resimlerin seçilen ürüne dahil edilmesini sağlayabilirsiniz.

Not: Bu resimler, Android marka kurallarına uygun olmalıdır.

Kurtarma Kullanıcı Arayüzü

Farklı donanımlara (fiziksel düğmeler, LED'ler, ekranlar vb.) sahip cihazları desteklemek için, durumu görüntülemek ve her cihaz için manuel olarak çalıştırılan gizli özelliklere erişmek için kurtarma arayüzünü özelleştirebilirsiniz.

Amacınız, cihaza özgü işlevsellik sağlamak için birkaç C++ nesnesiyle küçük bir statik kitaplık oluşturmaktır. bootable/recovery/default_device.cpp dosyası varsayılan olarak kullanılır ve bu dosyanın cihazınız için bir sürümünü yazarken kopyalamak için iyi bir başlangıç ​​noktasıdır.

Not: Burada Komut Yok yazan bir mesaj görebilirsiniz. Metni değiştirmek için ses açma düğmesine basarken güç düğmesini basılı tutun. Aygıtlarınızda her iki düğme de yoksa, metin arasında geçiş yapmak için herhangi bir düğmeye uzun basın.

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

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

Başlık ve öğe işlevleri

Device sınıfı, gizli kurtarma menüsünde görünen başlıkları ve öğeleri döndürmek için işlevler gerektirir. Başlıklar, menünün nasıl çalıştırılacağını açıklar (vurgulanan öğeyi değiştirmek/seçmek için kontroller).

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 };

Not: Uzun çizgiler kesilir (sarılmaz), bu nedenle cihazınızın ekran genişliğini göz önünde bulundurun.

CheckKey'i özelleştirme

Ardından, cihazınızın RecoveryUI uygulamasını tanımlayın. Bu örnek, tardis cihazının bir ekranı olduğunu varsayar, bu nedenle yerleşik ScreenRecoveryUIuygulamasından devralabilirsiniz ( ekranı olmayan cihazlar için talimatlara bakın CheckKey() .

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

ANAHTAR sabitler

KEY_* sabitleri linux/input.h içinde tanımlanmıştır. CheckKey() kurtarmanın geri kalanında ne olup bittiğine bakılmaksızın çağrılır: menü kapatıldığında, açıldığında, paket kurulumu sırasında, userdata silinirken, vb. Dört sabitten birini döndürebilir:

  • GEÇİŞ . Menünün ve/veya metin oturumunun görüntülenmesini açın veya kapatın
  • YENİDEN BAŞLAT Cihazı hemen yeniden başlatın
  • GÖRMEYİN . Bu tuşa basmayı yoksay
  • . Bu tuşa basmayı eşzamanlı olarak tüketilecek şekilde sıralayın (yani, ekran etkinse kurtarma menüsü sistemi tarafından)

Bir key-down olayının ardından aynı anahtar için bir key-up olayı her geldiğinde CheckKey() çağrılır. (A-down B-down B-up A-up olaylarının sırası yalnızca CheckKey(B) çağrılmasıyla sonuçlanır.) CheckKey() , diğer tuşların basılı tutulup tutulmadığını öğrenmek için IsKeyPressed() çağırabilir. (Yukarıdaki önemli olaylar dizisinde, CheckKey(B) IsKeyPressed(A) olarak adlandırılırsa, true değerini döndürürdü.)

CheckKey() sınıfında durumu koruyabilir; bu, anahtar dizilerini algılamak için yararlı olabilir. Bu örnek, biraz daha karmaşık bir kurulumu gösterir: güç düğmesi basılı tutulup ses artırma düğmesine basılarak ekran değiştirilir ve güç düğmesine art arda beş kez basılarak (araya başka hiçbir tuş girmeden) cihaz hemen yeniden başlatılabilir:

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;
    }
};

Ekran Kurtarma Kullanıcı Arayüzü

ScreenRecoveryUI ile kendi resimlerinizi (hata simgesi, kurulum animasyonu, ilerleme çubukları) kullanırken, animasyonların saniye başına kare (FPS) cinsinden hızını kontrol etmek için animation_fps değişkenini ayarlayabilirsiniz.

Not: Geçerli interlace-frames.py komut dosyası, animation_fps bilgilerini görüntünün kendisinde saklamanıza olanak tanır. Android'in önceki sürümlerinde, animation_fps kendiniz ayarlamak gerekliydi.

animation_fps değişkenini ayarlamak için, alt sınıfınızdaki ScreenRecoveryUI::Init() işlevini geçersiz kılın. Değeri ayarlayın, ardından başlatmayı tamamlamak için parent Init() işlevini çağırın. Varsayılan değer (20 FPS), varsayılan kurtarma görüntülerine karşılık gelir; bu görüntüleri kullanırken bir Init() işlevi sağlamanız gerekmez. Görüntülerle ilgili ayrıntılar için bkz. Kurtarma Kullanıcı Arabirimi Görüntüleri .

Cihaz Sınıfı

Bir RecoveryUI uygulamasına sahip olduktan sonra, cihaz sınıfınızı tanımlayın (yerleşik Cihaz sınıfından alt sınıf). UI sınıfınızın tek bir örneğini oluşturmalı ve bunu GetUI() işlevinden döndürmelidir:

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

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

    RecoveryUI* GetUI() { return ui; }

Düzeltmeye başla

StartRecovery() yöntemi, kurtarma başlangıcında, kullanıcı arabirimi başlatıldıktan ve bağımsız değişkenler ayrıştırıldıktan sonra, ancak herhangi bir işlem yapılmadan önce çağrılır. Varsayılan uygulama hiçbir şey yapmaz, dolayısıyla yapacak bir şeyiniz yoksa bunu alt sınıfınızda sağlamanız gerekmez:

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

Kurtarma menüsünün sağlanması ve yönetilmesi

Sistem, başlık satırlarının listesini ve öğelerin listesini almak için iki yöntem çağırır. Bu uygulamada, dosyanın başında tanımlanan statik dizileri döndürür:

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

HandleMenuKey

Ardından, bir tuşa basmayı ve geçerli menü görünürlüğünü alan ve hangi eylemin gerçekleştirileceğine karar veren bir HandleMenuKey() işlevi sağlayın:

   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;
    }

Yöntem, bir anahtar kodunu (daha önce UI nesnesinin CheckKey() yöntemi tarafından işlenmiş ve kuyruğa alınmış) ve menü/metin günlüğü görünürlüğünün mevcut durumunu alır. Dönen değer bir tamsayıdır. Değer 0 veya daha yüksekse, hemen çağrılan bir menü öğesinin konumu olarak alınır (aşağıdaki InvokeMenuItem() yöntemine bakın). Aksi takdirde, aşağıdaki önceden tanımlanmış sabitlerden biri olabilir:

  • kVurguYukarı . Menü vurgusunu önceki öğeye taşı
  • kVurguAşağı . Menü vurgusunu bir sonraki öğeye taşı
  • kInvokeItem . Şu anda vurgulanan öğeyi çağır
  • kNoAction . Bu tuşa basarak hiçbir şey yapmayın

visible bağımsız değişkeninin ima ettiği gibi, menü görünür olmasa bile HandleMenuKey() çağrılır. CheckKey() den farklı olarak, kurtarma, verileri silme veya bir paket yükleme gibi bir şey yaparken çağrılmaz ; yalnızca kurtarma boştayken ve girdi beklerken çağrılır.

İztopu Mekanizmaları

Cihazınızda iztopu benzeri bir giriş mekanizması varsa (EV_REL türünde ve REL_Y kodunda giriş olayları oluşturur), kurtarma, iztopu benzeri giriş cihazı Y ekseninde hareket bildirdiğinde KEY_UP ve KEY_DOWN tuşlarına basılmasını sentezler. Tek yapmanız gereken KEY_UP ve KEY_DOWN olaylarını menü eylemlerine eşlemek. Bu eşleme CheckKey() için gerçekleşmez , dolayısıyla iztopu hareketlerini ekranı yeniden başlatmak veya değiştirmek için tetikleyici olarak kullanamazsınız.

Değiştirici Tuşlar

Değiştirici olarak tutulan anahtarları kontrol etmek için, kendi UI nesnenizin IsKeyPressed() yöntemini çağırın. Örneğin, bazı cihazlarda kurtarma sırasında Alt-W'ye basmak, menü görünse de görünmese de bir veri silme işlemi başlatırdı. Şu şekilde uygulayabilirsiniz:

   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
        }
        ...
    }

Not: görünür yanlış ise, kullanıcı vurguyu göremediği için menüyü değiştiren özel değerleri döndürmek (vurguyu taşı, vurgulanan öğeyi çağır) mantıklı değildir. Ancak, isterseniz değerleri iade edebilirsiniz.

Menü Öğesini Çağır

Ardından, GetMenuItems() tarafından döndürülen öğeler dizisindeki tamsayı konumlarını eylemlere eşleyen bir InvokeMenuItem() yöntemi sağlayın. tardis örneğindeki öğe dizisi için şunu kullanın:

   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;
        }
    }

Bu yöntem, sisteme bu eylemi gerçekleştirmesini söylemek için BuiltinAction numaralandırmasının herhangi bir üyesini (veya sistemin hiçbir şey yapmamasını istiyorsanız NO_ACTION üyesini) döndürebilir. Burası, sistemdekinin ötesinde ek kurtarma işlevi sağlama yeridir: Menünüze bunun için bir öğe ekleyin, o menü öğesi çağrıldığında burada yürütün ve sistemin başka hiçbir şey yapmaması için NO_ACTION döndürün.

BuiltinAction aşağıdaki değerleri içerir:

  • NO_ACTION . Hiçbir şey yapma.
  • YENİDEN BAŞLAT Recovery'den çıkın ve cihazı normal şekilde yeniden başlatın.
  • APPLY_EXT, APPLY_CACHE, APPLY_ADB_SIDELOAD . Çeşitli yerlerden bir güncelleme paketi kurun. Ayrıntılar için bkz. Yandan Yükleme .
  • WIPE_CACHE . Yalnızca önbellek bölümünü yeniden biçimlendirin. Nispeten zararsız olduğu için onay gerekmez.
  • WIPE_DATA . Fabrika verilerine sıfırlama olarak da bilinen kullanıcı verilerini ve önbellek bölümlerini yeniden biçimlendirin. Devam etmeden önce kullanıcıdan bu eylemi onaylaması istenir.

Son yöntem olan WipeData() isteğe bağlıdır ve bir veri silme işlemi başlatıldığında çağrılır (menü yoluyla kurtarmadan veya kullanıcı ana sistemden fabrika verilerine sıfırlama yapmayı seçtiğinde). Bu yöntem, kullanıcı verileri ve önbellek bölümleri silinmeden önce çağrılır. Cihazınız, kullanıcı verilerini bu iki bölüm dışında bir yerde saklıyorsa, buradan silmelisiniz. Başarıyı belirtmek için 0 ve başarısızlık için başka bir değer döndürmelisiniz, ancak şu anda dönüş değeri yok sayılır. Başarılı da olsanız başarısız da olsanız, kullanıcı verileri ve önbellek bölümleri silinir.

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

Cihaz Yap

Son olarak, Device sınıfınızın bir örneğini oluşturan ve döndüren make_device() işlevi için recovery_ui.cpp dosyasının sonuna bazı ortak metinler ekleyin:

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

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

recovery_ui.cpp dosyasını tamamladıktan sonra dosyayı oluşturun ve cihazınızdaki kurtarmaya bağlayın. Android.mk'de, yalnızca bu C++ dosyasını içeren bir statik kitaplık oluşturun:

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)

Ardından, bu aygıt için kart yapılandırmasında statik kitaplığınızı TARGET_RECOVERY_UI_LIB değeri olarak belirtin.

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

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

Kurtarma kullanıcı arabirimi görüntüleri

Kurtarma kullanıcı arabirimi görüntülerden oluşur. İdeal olarak, kullanıcılar kullanıcı arabirimiyle hiçbir zaman etkileşime girmez: Normal bir güncelleme sırasında, telefon kurtarma moduna geçer, yükleme ilerleme çubuğunu doldurur ve kullanıcı girişi olmadan yeni sisteme geri döner. Bir sistem güncelleme sorunu olması durumunda, yapılabilecek tek kullanıcı işlemi müşteri hizmetlerini aramaktır.

Yalnızca görüntü içeren bir arabirim, yerelleştirme ihtiyacını ortadan kaldırır. Ancak, Android 5.0'dan itibaren güncelleme, resimle birlikte bir metin dizisi (örn. "Sistem güncellemesi yükleniyor...") görüntüleyebilir. Ayrıntılar için bkz. Yerelleştirilmiş kurtarma metni .

Android 5.0 ve sonrası

Android 5.0 ve sonraki kurtarma kullanıcı arabirimi iki ana görüntü kullanır: hata görüntüsü ve yükleme animasyonu.

ota hatası sırasında gösterilen resim

Şekil 1. icon_error.png

ota kurulumu sırasında gösterilen resim

Şekil 2. icon_installing.png

Kurulum animasyonu, animasyonun farklı karelerinin satırlarla iç içe geçtiği tek bir PNG görüntüsü olarak temsil edilir (bu nedenle Şekil 2 ezilmiş görünür). Örneğin, 200x200 yedi karelik bir animasyon için, ilk karenin 0, 7, 14, 21, ... satırları olduğu tek bir 200x1400 görüntü oluşturun; ikinci çerçeve 1, 8, 15, 22, ... sıralarıdır; vb. Birleştirilen görüntü, animasyon karelerinin sayısını ve saniyedeki kare sayısını (FPS) gösteren bir metin öbeği içerir. bootable/recovery/interlace-frames.py aracı, bir dizi giriş çerçevesi alır ve bunları kurtarma tarafından kullanılan gerekli bileşik görüntüde birleştirir.

Varsayılan görüntüler farklı yoğunluklarda mevcuttur ve bootable/recovery/res-$DENSITY/images konumunda bulunur (örn. bootable/recovery/res-hdpi/images ). Yükleme sırasında statik bir görüntü kullanmak için, yalnızca icon_installing.png görüntüsünü sağlamanız ve animasyondaki kare sayısını 0 olarak ayarlamanız gerekir (hata simgesi animasyonlu değildir; her zaman statik bir görüntüdür).

Android 4.x ve öncesi

Android 4.x ve önceki kurtarma kullanıcı arabirimi, hata görüntüsünü (yukarıda gösterilen) ve yükleme animasyonunu ve birkaç bindirme görüntüsünü kullanır:

ota kurulumu sırasında gösterilen resim

Şekil 3. icon_installing.png

ilk bindirme olarak gösterilen resim

Şekil 4. icon-installing_overlay01.png

yedinci bindirme olarak gösterilen resim

Şekil 5. icon_installing_overlay07.png

Yükleme sırasında, ekran görüntüsü, icon_installing.png görüntüsü çizilerek ve ardından kaplama çerçevelerinden biri bunun üzerine uygun ofsetle çizilerek oluşturulur. Burada, bindirmenin temel görüntünün üzerine yerleştirildiği yeri vurgulamak için kırmızı bir kutu bindirilir:

yükleme ve ilk bindirmenin bileşik görüntüsü

Şekil 6. Animasyon karesi 1'i yükleme (icon_installing.png + icon_installing_overlay01.png)

yükleme artı yedinci bindirmenin bileşik görüntüsü

Şekil 7. Animasyon karesi 7'yi yükleme (icon_installing.png + icon_installing_overlay07.png)

Sonraki çerçeveler, zaten orada olanın üstüne yalnızca bir sonraki yer paylaşımlı görüntü çizilerek görüntülenir; temel görüntü yeniden çizilmez.

Animasyondaki kare sayısı, istenen hız ve kaplamanın tabana göre x ve y ofsetleri, ScreenRecoveryUI sınıfının üye değişkenleri tarafından belirlenir. Varsayılan görüntüler yerine özel görüntüler kullanırken, özel görüntüleriniz için bu değerleri değiştirmek üzere alt sınıfınızdaki Init() yöntemini geçersiz kılın (ayrıntılar için bkz. ScreenRecoveryUI ). bootable/recovery/make-overlay.py komut dosyası, gerekli ofsetlerin hesaplanması da dahil olmak üzere, bir dizi görüntü karesini kurtarma için gereken "temel görüntü + bindirme görüntüleri" formuna dönüştürmeye yardımcı olabilir.

Varsayılan görüntüler bootable/recovery/res/images konumunda bulunur. Yükleme sırasında statik bir görüntü kullanmak için, yalnızca icon_installing.png görüntüsünü sağlamanız ve animasyondaki kare sayısını 0 olarak ayarlamanız gerekir (hata simgesi animasyonlu değildir; her zaman statik bir görüntüdür).

Yerelleştirilmiş kurtarma metni

Android 5.x, resimle birlikte bir dizi metin (örn. "Sistem güncellemesi yükleniyor...") görüntüler. Ana sistem kurtarmaya önyükleme yaptığında, kullanıcının geçerli yerel ayarını kurtarmaya bir komut satırı seçeneği olarak iletir. Kurtarma, görüntülenecek her mesaj için, her yerel ayarda o mesaj için önceden işlenmiş metin dizeleri içeren ikinci bir bileşik görüntü içerir.

Kurtarma metni dizelerinin örnek görüntüsü:

kurtarma metninin resmi

Şekil 8. Kurtarma mesajları için yerelleştirilmiş metin

Kurtarma metni aşağıdaki mesajları görüntüleyebilir:

  • Sistem güncellemesi yükleniyor...
  • Hata!
  • Siliniyor... (veri silme/fabrika ayarlarına sıfırlama işlemi yapılırken)
  • Komut yok (kullanıcı manuel olarak kurtarmaya başladığında)

bootable/recovery/tools/recovery_l10n/ içindeki Android uygulaması, bir mesajın yerelleştirmelerini işler ve bileşik görüntüyü oluşturur. Bu uygulamayı kullanmayla ilgili ayrıntılar için bootable/recovery/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java adresindeki yorumlara bakın.

Bir kullanıcı manuel olarak kurtarmaya önyükleme yaptığında, yerel ayar kullanılamayabilir ve herhangi bir metin görüntülenmeyebilir. Metin mesajlarını kurtarma işlemi için kritik hale getirmeyin.

Not: Günlük mesajlarını görüntüleyen ve kullanıcının menüden eylemleri seçmesine izin veren gizli arayüz yalnızca İngilizce olarak mevcuttur.

İlerleme çubukları

İlerleme çubukları, ana görüntünün (veya animasyonun) altında görünebilir. İlerleme çubuğu, aynı boyutta olması gereken iki giriş görüntüsünü birleştirerek yapılır:

boş ilerleme çubuğu

Şekil 9. progress_empty.png

tam ilerleme çubuğu

Şekil 10. progress_fill.png

İlerleme çubuğunu oluşturmak için dolgu görüntüsünün sol ucu, boş görüntünün sağ ucunun yanında görüntülenir. İki görüntü arasındaki sınırın konumu, ilerlemeyi belirtmek için değiştirilir. Örneğin, yukarıdaki giriş görüntüsü çiftleriyle şunu görüntüleyin:

ilerleme çubuğu %1'de

Şekil 11. İlerleme çubuğu %1'de>

ilerleme çubuğu %10'da

Şekil 12. %10'da ilerleme çubuğu

ilerleme çubuğu %50'de

Şekil 13. %50'de ilerleme çubuğu

Bu görüntüleri (bu örnekte) device/yoyodyne/tardis/recovery/res/images içine yerleştirerek cihaza özel sürümlerini sağlayabilirsiniz. Dosya adları yukarıda listelenenlerle eşleşmelidir; Bu dizinde bir dosya bulunduğunda, derleme sistemi onu karşılık gelen varsayılan görüntüye tercih ederek kullanır. Yalnızca 8 bit renk derinliğine sahip RGB veya RGBA biçimindeki PNG'ler desteklenir.

Not: Android 5.x'te, yerel ayar kurtarma tarafından biliniyorsa ve sağdan sola (RTL) bir dilse (Arapça, İbranice vb.), ilerleme çubuğu sağdan sola doğru dolar.

Ekransız cihazlar

Tüm Android cihazların ekranı yoktur. Cihazınız başsız bir cihazsa veya yalnızca sesli bir arabirime sahipse, kurtarma kullanıcı arabiriminde daha kapsamlı özelleştirmeler yapmanız gerekebilir. ScreenRecoveryUI'nin bir alt sınıfını oluşturmak yerine doğrudan üst sınıf RecoveryUI'nin alt sınıfını oluşturun.

RecoveryUI, "ekranı değiştir", "ilerleme çubuğunu güncelle", "menüyü göster", "menü seçimini değiştir" vb. gibi daha düşük düzey kullanıcı arabirimi işlemlerini gerçekleştirmek için yöntemlere sahiptir. Uygun bir arabirim sağlamak için bunları geçersiz kılabilirsiniz. cihazınız için. Belki cihazınızda durumu belirtmek için farklı renkler veya yanıp sönme desenleri kullanabileceğiniz veya ses çalabileceğiniz LED'ler vardır. (Belki de bir menüyü veya "metin görüntüleme" modunu hiç desteklemek istemezsiniz; ekranı asla açmayan veya bir menü öğesi seçmeyen CheckKey() ve HandleMenuKey() uygulamalarıyla bunlara erişimi engelleyebilirsiniz. Bu durumda , sağlamanız gereken RecoveryUI yöntemlerinin çoğu yalnızca boş taslaklar olabilir.)

Hangi yöntemleri desteklemeniz gerektiğini görmek için RecoveryUI bildirimi için bootable/recovery/ui.h bölümüne bakın. RecoveryUI soyuttur - bazı yöntemler tamamen sanaldır ve alt sınıflar tarafından sağlanmalıdır - ancak anahtar girdilerin işlenmesi için gereken kodu içerir. Cihazınızda anahtar yoksa veya bunları farklı şekilde işlemek istiyorsanız bunu da geçersiz kılabilirsiniz.

güncelleyici

Güncelleyici betiğinizden çağrılabilen kendi uzantı işlevlerinizi sağlayarak, güncelleme paketinin kurulumunda cihaza özgü kodu kullanabilirsiniz. İşte tardis cihazı için örnek bir fonksiyon:

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

#include "edify/expr.h"

Her uzantı işlevi aynı imzaya sahiptir. Bağımsız değişkenler, işlevin çağrıldığı ad, bir State* çerezi, gelen bağımsız değişkenlerin sayısı ve bağımsız değişkenleri temsil eden bir Expr* işaretçileri dizisidir. Dönen değer, yeni tahsis edilmiş bir Value* dır.

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);
    }

Argümanlarınız, işleviniz çağrıldığında değerlendirilmemiştir; hangilerinin kaç kez değerlendirileceğini işlevinizin mantığı belirler. Böylece, kendi kontrol yapılarınızı uygulamak için uzantı fonksiyonlarını kullanabilirsiniz. Bir Expr* bağımsız değişkenini değerlendirmek için Call Evaluate() ve bir Value* döndürün. Evaluate() NULL döndürürse, tuttuğunuz tüm kaynakları serbest bırakmalı ve hemen NULL döndürmelisiniz (bu, düzenleme yığınını iptal eder). Aksi takdirde, döndürülen Değerin sahipliğini alırsınız ve sonuçta üzerinde FreeValue() çağırmaktan siz sorumlu olursunuz.

İşlevin iki bağımsız değişkene ihtiyacı olduğunu varsayalım: dize değerli bir anahtar ve damla değerli bir görüntü . Bunun gibi argümanları okuyabilirsiniz:

   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;
    }

NULL'u kontrol etmek ve daha önce değerlendirilen bağımsız değişkenleri serbest bırakmak, birden çok bağımsız değişken için can sıkıcı olabilir. ReadValueArgs() işlevi bunu kolaylaştırabilir. Yukarıdaki kod yerine şunu yazabilirdiniz:

   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() tip kontrolü yapmaz, bu yüzden bunu burada yapmalısınız; başarısız olduğunda biraz daha az belirgin bir hata mesajı üretmek pahasına bunu tek bir if ifadesiyle yapmak daha uygundur. Ancak ReadValueArgs() her bağımsız değişkeni değerlendirmeyi ve değerlendirmelerden herhangi birinin başarısız olması durumunda önceden değerlendirilen tüm bağımsız değişkenleri serbest bırakmayı (ayrıca yararlı bir hata mesajı ayarlamayı) ele alır. Değişken sayıda argümanı değerlendirmek için bir ReadValueVarArgs() uygunluk işlevini kullanabilirsiniz (bir Value* dizisi döndürür).

Bağımsız değişkenleri değerlendirdikten sonra, işlevin işini yapın:

   // 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 ...

Dönen değer bir Value* nesnesi olmalıdır; bu nesnenin mülkiyeti arayana geçer. Çağıran kişi, bu Value* tarafından işaret edilen tüm verilerin, özellikle de veri üyesinin sahipliğini üstlenir.

Bu örnekte, başarıyı belirtmek için doğru veya yanlış bir değer döndürmek istiyorsunuz. Boş dizenin false ve diğer tüm dizelerin true olduğu kuralını unutmayın. Çağıran her ikisini de free() , döndürmek için sabit dizgenin malloc'lu bir kopyasına sahip bir Value nesnesini malloc etmelisiniz. Argümanlarınızı değerlendirerek elde ettiğiniz nesneler üzerinde FreeValue() çağırmayı unutmayın!

   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;
}

StringValue() kolaylık işlevi, bir dizeyi yeni bir Value nesnesine sarar. Yukarıdaki kodu daha kısa ve öz bir şekilde yazmak için kullanın:

   FreeValue(key);
    FreeValue(image);

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

İşlevleri düzenleme yorumlayıcısına bağlamak için, Register_ foo işlevini sağlayın; burada foo , bu kodu içeren statik kitaplığın adıdır. Her uzantı işlevini kaydetmek için RegisterFunction() öğesini çağırın. Geleneksel olarak, aygıta özgü işlevleri device . whatever Eklenen gelecekteki yerleşik işlevlerle çakışmaları önlemek için device . whatever .

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

Artık makefile'ı kodunuzla statik bir kitaplık oluşturacak şekilde yapılandırabilirsiniz. (Bu, önceki bölümde kurtarma kullanıcı arayüzünü özelleştirmek için kullanılan aynı makefile'dir; cihazınızda burada tanımlanan her iki statik kitaplık da olabilir.)

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

Statik kitaplığın adı, içinde bulunan Register_ libname işlevinin adıyla eşleşmelidir.

LOCAL_MODULE := librecovery_updater_tardis
include $(BUILD_STATIC_LIBRARY)

Son olarak, kitaplığınızı çekmek için kurtarma derlemesini yapılandırın. Kitaplığınızı TARGET_RECOVERY_UPDATER_LIBS'e ekleyin (birden çok kitaplık içerebilir; hepsi kaydedilir). Kodunuz, kendileri düzenleme uzantıları olmayan diğer statik kitaplıklara bağlıysa (yani, bir Register_ libname işlevine sahip değiller), bunları (var olmayan) kayıt işlevlerini çağırmadan güncelleyiciye bağlamak için TARGET_RECOVERY_UPDATER_EXTRA_LIBS içinde listeleyebilirsiniz. Örneğin, cihazınıza özel kodunuz veri sıkıştırmasını açmak için zlib'i kullanmak istiyorsa libz'yi buraya eklersiniz.

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 +=

OTA paketinizdeki güncelleyici betikleri artık işlevinizi diğerleri gibi çağırabilir. Tardis cihazınızı yeniden programlamak için güncelleme betiği şunları içerebilir: tardis.reprogram("the-key", package_extract_file("tardis-image.dat")) . Bu, yeni uzantı işlevine ikinci bağımsız değişkeni üretmek için güncelleme paketinden çıkarılan bir dosyanın içeriğini bir damla olarak döndüren yerleşik package_extract_file() işlevinin tek bağımsız değişkenli sürümünü kullanır.

OTA paketi oluşturma

Son bileşen, OTA paketi oluşturma araçlarının cihazınıza özel veriler hakkında bilgi sahibi olmasını sağlamak ve uzantı işlevlerinize yapılan çağrıları içeren güncelleyici komut dosyaları yaymaktır.

İlk olarak, derleme sisteminin cihaza özgü bir veri bloğu hakkında bilgi sahibi olmasını sağlayın. Veri dosyanızın device/yoyodyne/tardis/tardis.dat konumunda olduğunu varsayarak, cihazınızın AndroidBoard.mk dosyasında aşağıdakileri belirtin:

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

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

Bunun yerine onu bir Android.mk'ye de koyabilirsiniz, ancak hangi cihaz oluşturulursa oluşturulsun ağaçtaki tüm Android.mk dosyaları yüklendiğinden, bir cihaz kontrolü ile korunması gerekir. (Ağacınızda birden fazla cihaz varsa, tardis cihazını oluştururken yalnızca tardis.dat dosyasının eklenmesini istersiniz.)

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

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

Bunlara tarihsel nedenlerle radyo dosyaları denir; cihaz radyosuyla (varsa) hiçbir ilgileri olmayabilir. Bunlar, oluşturma sisteminin OTA oluşturma araçları tarafından kullanılan hedef dosyalar .zip'e kopyaladığı opak veri damlalarıdır. Bir derleme yaptığınızda tardis.dat, target-files.zip dosyasında RADIO/tardis.dat olarak depolanır. İstediğiniz kadar dosya eklemek için add-radio-file birden çok kez arayabilirsiniz.

Python modülü

Sürüm araçlarını genişletmek için, varsa araçların arayabileceği bir Python modülü (releasetools.py olarak adlandırılmalıdır) yazın. Örnek:

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"));""")

Ayrı bir işlev, artımlı bir OTA paketi oluşturma durumunu ele alır. Bu örnek için, tardis'i yalnızca tardis.dat dosyası iki yapı arasında değiştiğinde yeniden programlamanız gerektiğini varsayalım.

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"));""")

Modül fonksiyonları

Modülde aşağıdaki işlevleri sağlayabilirsiniz (yalnızca ihtiyacınız olanları uygulayın).

FullOTA_Assertions()
Tam bir OTA oluşturmanın başlangıcına yakın çağrılır. Bu, cihazın mevcut durumu hakkında iddialar yayınlamak için iyi bir yerdir. Aygıtta değişiklik yapan betik komutları yaymayın.
FullOTA_InstallBegin()
Cihaz durumuyla ilgili tüm iddialar geçtikten sonra ancak herhangi bir değişiklik yapılmadan önce çağrılır. Cihazda herhangi bir değişiklik yapılmadan önce çalıştırılması gereken, cihaza özel güncellemeler için komutlar gönderebilirsiniz.
FullOTA_InstallEnd()
Komut dosyası oluşturmanın sonunda, önyükleme ve sistem bölümlerini güncellemek için komut dosyası komutları yayınlandıktan sonra çağrılır. Cihaza özgü güncellemeler için ek komutlar da gönderebilirsiniz.
IncrementalOTA_Assertions()
FullOTA_Assertions() a benzer, ancak artımlı bir güncelleme paketi oluşturulurken çağrılır.
IncrementalOTA_VerifyBegin()
Cihaz durumuyla ilgili tüm iddialar geçtikten sonra ancak herhangi bir değişiklik yapılmadan önce çağrılır. Cihazda herhangi bir değişiklik yapılmadan önce çalıştırılması gereken, cihaza özel güncellemeler için komutlar gönderebilirsiniz.
IncrementalOTA_VerifyEnd()
Doğrulama aşamasının sonunda, komut dosyası dokunacağı dosyaların beklenen başlangıç ​​içeriğine sahip olduğunu doğrulamayı bitirdiğinde çağrılır. Bu noktada cihazda hiçbir şey değiştirilmedi. Ayrıca, cihaza özel ek doğrulamalar için de kod gönderebilirsiniz.
IncrementalOTA_InstallBegin()
Yama uygulanacak dosyaların, herhangi bir değişiklik yapılmadan önce beklenen önceki duruma sahip olduğu doğrulandıktan sonra çağrılır. Cihazda herhangi bir değişiklik yapılmadan önce çalıştırılması gereken, cihaza özel güncellemeler için komutlar gönderebilirsiniz.
IncrementalOTA_InstallEnd()
Tam OTA paketi muadiline benzer şekilde, bu, komut dosyası oluşturma işleminin sonunda, önyüklemeyi ve sistem bölümlerini güncellemek için komut dosyası komutları yayınlandıktan sonra çağrılır. Cihaza özgü güncellemeler için ek komutlar da gönderebilirsiniz.

Not: Cihazın gücü kesilirse, OTA kurulumu baştan başlayabilir. Bu komutların halihazırda tamamen veya kısmen çalıştırıldığı cihazlarla başa çıkmaya hazır olun.

İşlevleri bilgi nesnelerine geçirme

İşlevleri, çeşitli faydalı öğeler içeren tek bir bilgi nesnesine iletin:

  • info.input_zip . (Yalnızca tam OTA'lar) Giriş hedef dosyaları .zip için zipfile.ZipFile nesnesi.
  • info.source_zip . (Yalnızca Artımlı OTA'lar) Kaynak hedef dosyalar .zip için zipfile.ZipFile nesnesi (artımlı paket yüklenirken cihazda zaten bulunan derleme).
  • info.target_zip . (Yalnızca Artımlı OTA'lar) Hedef hedef dosyalar için zipfile.ZipFile nesnesi .zip (artımlı paketin aygıta yerleştirdiği yapı).
  • bilgi.output_zip . Paket oluşturuluyor; yazma için açılan bir zipfile.ZipFile nesnesi. Pakete bir dosya eklemek için common.ZipWriteStr(info.output_zip, filename , data ) kullanın.
  • bilgi.script . Komut ekleyebileceğiniz komut dosyası nesnesi. Komut dosyasına metin çıktısı almak için info.script.AppendExtra( script_text ) öğesini çağırın. Çıktı metninin noktalı virgülle bittiğinden emin olun, böylece daha sonra verilen komutlarla çalışmaz.

Bilgi nesnesi hakkında ayrıntılar için, ZIP arşivleri için Python Software Foundation belgelerine bakın.

Modül konumunu belirtin

BoardConfig.mk dosyanızda cihazınızın releasetools.py betiğinin konumunu belirtin:

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

TARGET_RELEASETOOLS_EXTENSIONS := device/yoyodyne/tardis

TARGET_RELEASETOOLS_EXTENSIONS ayarlanmamışsa, varsayılan olarak $(TARGET_DEVICE_DIR)/../common dizini (bu örnekte device/yoyodyne/common ) olur. Releasetools.py betiğinin konumunu açıkça tanımlamak en iyisidir. Tardis aygıtı oluşturulurken, releasetools.py komut dosyası, hedef dosyalar .zip dosyasına ( META/releasetools.py ) dahil edilir.

Sürüm araçlarını ( img_from_target_files veya ota_from_target_files ) çalıştırdığınızda, varsa, Android kaynak ağacından olan target-files .zip dosyasındaki releasetools.py komut dosyası tercih edilir. Cihaza özgü uzantıların yolunu, en yüksek önceliği alan -s (veya --device_specific ) seçeneğiyle de açıkça belirtebilirsiniz. Bu, yayın araçları uzantılarında hataları düzeltmenize ve değişiklikler yapmanıza ve bu değişiklikleri eski hedef dosyalara uygulamanıza olanak tanır.

Şimdi, ota_from_target_files çalıştırdığınızda, otomatik olarak target_files .zip dosyasından cihaza özgü modülü alır ve OTA paketleri oluştururken kullanır:

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

Alternatif olarak, ota_from_target_files çalıştırdığınızda cihaza özel uzantılar belirleyebilirsiniz.

./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

Not: Seçeneklerin tam listesi için build/make/tools/releasetools/ota_from_target_files içindeki ota_from_target_files yorumlarına bakın.

Yan yükleme

Recovery, bir güncelleme paketini ana sistem tarafından kablosuz olarak indirmeden manuel olarak yüklemek için yandan yükleme mekanizmasına sahiptir. Yandan yükleme, ana sistemin önyüklenemediği cihazlarda hata ayıklamak veya değişiklik yapmak için kullanışlıdır.

Tarihsel olarak, yandan yükleme, paketlerin cihazın SD kartından yüklenmesi yoluyla yapılmıştır; önyükleme yapmayan bir cihaz olması durumunda, paket başka bir bilgisayar kullanılarak SD karta yerleştirilebilir ve ardından SD kart cihaza takılabilir. Çıkarılabilir harici depolamaya sahip olmayan Android cihazları barındırmak için kurtarma, dışarıdan yükleme için iki ek mekanizmayı destekler: paketleri önbellek bölümünden yüklemek ve bunları adb kullanarak USB üzerinden yüklemek.

To invoke each sideload mechanism, your device's Device::InvokeMenuItem() method can return the following values of BuiltinAction:

  • APPLY_EXT . Sideload an update package from external storage ( /sdcard directory). Your recovery.fstab must define the /sdcard mount point. This is not usable on devices that emulate an SD card with a symlink to /data (or some similar mechanism). /data is typically not available to recovery because it may be encrypted. The recovery UI displays a menu of .zip files in /sdcard and allows the user to select one.
  • APPLY_CACHE . Similar to loading a package from /sdcard except that the /cache directory (which is always available to recovery) is used instead. From the regular system, /cache is only writable by privileged users, and if the device isn't bootable then the /cache directory can't be written to at all (which makes this mechanism of limited utility).
  • APPLY_ADB_SIDELOAD . Allows user to send a package to the device via a USB cable and the adb development tool. When this mechanism is invoked, recovery starts up its own mini version of the adbd daemon to let adb on a connected host computer talk to it. This mini version supports only a single command: adb sideload filename . The named file is sent from the host machine to the device, which then verifies and installs it just as if it had been on local storage.

A few caveats:

  • Only USB transport is supported.
  • If your recovery runs adbd normally (usually true for userdebug and eng builds), that will be shut down while the device is in adb sideload mode and will be restarted when adb sideload has finished receiving a package. While in adb sideload mode, no adb commands other than sideload work ( logcat , reboot , push , pull , shell , etc. all fail).
  • You cannot exit adb sideload mode on the device. To abort, you can send /dev/null (or anything else that's not a valid package) as the package, and then the device will fail to verify it and stop the installation procedure. The RecoveryUI implementation's CheckKey() method will continue to be called for keypresses, so you can provide a key sequence that reboots the device and works in adb sideload mode.