Cihaza özel kod

Kurtarma sistemi, cihaza özel kodun eklenmesi için çeşitli kancalar içerir; böylece OTA güncellemeleri, cihazın Android sistemi dışındaki parçalarını da (örneğin, temel bant veya radyo işlemcisi) güncelleyebilir.

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

Bölüm haritası

Android 2.3'ten itibaren platform, eMMc flash aygıtlarını ve bu aygıtlarda çalışan ext4 dosya sistemini desteklemektedir. Ayrıca Bellek Teknolojisi Aygıtı (MTD) flash aygıtlarını ve eski sürümlerdeki 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. Harita dosyasının adını BoardConfig.mk'deki TARGET_RECOVERY_FSTAB'da 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ının tanımlanması gerekir (aygıtlar ayrıca ekstra bölümler de ekleyebilir). Desteklenen beş dosya sistemi türü vardır:

yaffs2
MTD flash aygıtının üzerindeki yaffs2 dosya sistemi. "device", 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 gerçekte bağlanmamıştır ancak bağlama noktası bölümü bulmak için bir anahtar olarak kullanılır. "device" /proc/mtd içindeki MTD bölümünün adı olmalıdır.
dahili4
Bir eMMc flash aygıtının üzerindeki 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 türüne benzer şekilde, eMMc hiçbir zaman gerçekte bağlanmaz, ancak bağlama noktası dizesi, aygıtı tabloda bulmak için kullanılır.
vfat
Genellikle SD kart gibi harici depolama için bir blok aygıtının üzerindeki FAT dosya sistemi. Cihaz blok cihazdır; cihaz2, birincil cihazın montajı başarısız olursa sistemin monte etmeye çalıştığı ikinci blok cihazdır (bölümleme tablosu ile formatlanmış veya formatlanmamış SD kartlarla uyumluluk için).

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

Android 3.0'dan başlayarak, Recovery.fstab dosyasına isteğe bağlı ek bir alan olan options eklenir. Şu anda tanımlanmış tek seçenek, bölümün uzunluğunu açıkça belirtmenize olanak tanıyan 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 formatlanacak boyut alınır. Örneğin, "uzunluk=-16384" ayarı, söz konusu bölüm yeniden biçimlendirildiğinde söz konusu bölümün son 16k'sinin üzerine yazılmayacağı anlamına gelir. Bu, kullanıcı verileri bölümünün şifrelenmesi (şifreleme meta verilerinin üzerine yazılmaması gereken bölümün sonunda depolandığı yer) gibi özellikleri destekler.

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

Önyükleme animasyonu

Cihaz üreticileri, bir Android cihazı başlatılırken gösterilen animasyonu özelleştirme olanağına sahiptir. Bunu yapmak için, önyükleme animasyonu biçimindeki spesifikasyonlara göre düzenlenmiş ve konumlandırılmış bir .zip dosyası oluşturun.

Android Things cihazları için, resimlerin seçilen ürüne dahil edilmesi için sıkıştırılmış dosyayı Android Things konsoluna yükleyebilirsiniz.

Not: Bu görsellerin Android marka kurallarına uygun olması gerekir.

Kurtarma Kullanıcı Arayüzü

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

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

Not: Burada Komut Yok diyen bir mesaj görebilirsiniz. Metni değiştirmek için ses açma düğmesine basarken güç düğmesini basılı tutun. Cihazlarınızda her iki düğme de yoksa metni değiştirmek 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 (örn. vurgulanan öğeyi değiştirme/seçme kontrolleri).

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 kısaltılmıştır (sarılmamıştır), bu nedenle cihazınızın ekranının genişliğini aklınızda bulundurun.

CheckKey'i özelleştirin

Daha sonra cihazınızın RecoveryUI uygulamasını tanımlayın. Bu örnekte tardis cihazının bir ekranı olduğu varsayılmaktadır, böylece yerleşik ScreenRecoveryUI uygulamasından miras alabilirsiniz ( ekranı olmayan cihazlar için talimatlara bakın.) ScreenRecoveryUI'dan özelleştirilecek tek işlev, ilk eşzamansız anahtar işlemeyi yapan CheckKey() işlevidir:

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 dosyasında tanımlanmıştır. Kurtarma işleminin geri kalanında ne olup bittiğine bakılmaksızın CheckKey() çağrılır: menü kapatıldığında, açıldığında, paket kurulumu sırasında, kullanıcı verilerinin silinmesi sırasında vb. Dört sabitten birini döndürebilir:

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

CheckKey() aynı anahtar için bir anahtar açma olayının ardından bir anahtar açma olayının takip ettiği her seferde çağrılır. (A-aşağı B-aşağı B-yukarı A-yukarı olay 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) çağırırsa true değerini döndürürdü.)

CheckKey() kendi sınıfındaki durumu koruyabilir; bu, tuş dizilerini tespit etmek için yararlı olabilir. Bu örnekte biraz daha karmaşık bir kurulum gösterilmektedir: Güç basılı tutularak ve ses açma tuşuna basılarak ekran değiştirilir ve güç düğmesine art arda beş kez basılarak cihaz hemen yeniden başlatılabilir (araya giren başka tuşlar olmadan):

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 görsellerinizi (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 betiği, animation_fps bilgilerini görüntünün kendisinde saklamanıza olanak tanır. Android'in önceki sürümlerinde, animation_fps kendiniz ayarlamanız gerekiyordu.

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 ve 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ıza gerek yoktur. Görüntülerle ilgili ayrıntılar için bkz. Kurtarma Kullanıcı Arayüzü Görüntüleri .

Cihaz sınıfı

RecoveryUI uygulamanızı yaptıktan sonra cihaz sınıfınızı tanımlayın (yerleşik Cihaz sınıfından alt sınıfa ayrılır). 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, kurtarmanın başlangıcında, kullanıcı arayüzü 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ıza gerek yoktur:

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

Kurtarma menüsünü sağlayın ve yönetin

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

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

KolMenüAnahtarı

Daha sonra, 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 (UI nesnesinin CheckKey() yöntemi tarafından daha önce işlenmiş ve kuyruğa alınmış olan) ve menü/metin günlüğü görünürlüğünün geçerli durumunu alır. Dönüş değeri bir tamsayıdır. Değer 0 veya daha yüksekse bu, 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:

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

Görünür argümanın ima ettiği gibi, menü görünür olmasa bile HandleMenuKey() çağrılır. CheckKey() dan farklı olarak, kurtarma, verileri silme veya bir paket yükleme gibi bir işlem yaparken çağrılmaz ; yalnızca kurtarma boştayken ve girişi beklerken çağrılır.

İztopu mekanizmaları

Cihazınızın hareket topuna benzer bir giriş mekanizması varsa (EV_REL türünde ve REL_Y koduyla giriş olayları oluşturur), iztopu benzeri giriş cihazı Y ekseninde hareket bildirdiğinde kurtarma, KEY_UP ve KEY_DOWN tuşlarını sentezler. Tek yapmanız gereken KEY_UP ve KEY_DOWN olaylarını menü eylemlerine eşlemektir. Bu eşleme CheckKey() için gerçekleşmez , bu nedenle 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 basılı 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 tuşlarına basıldığında, menü görünür olsa da olmasa da veri silme işlemi başlatılıyor. Bu ş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ışsa, kullanıcı vurguyu göremediği için menüyü değiştiren özel değerleri (vurguyu taşıma, vurgulanan öğeyi çağırma) döndürmenin bir anlamı yoktur. Ancak isterseniz değerleri döndürebilirsiniz.

InvokeMenuItem

Daha sonra, 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 bildirmek için YerleşikAction 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şlevselliği sağlayan yerdir: Menünüze bunun için bir öğe ekleyin, o menü öğesi çağrıldığında onu burada yürütün ve sistemin başka hiçbir şey yapmaması için NO_ACTION değerini döndürün.

YerleşikAction aşağıdaki değerleri içerir:

  • HİÇBİR EYLEM . Hiçbir şey yapma.
  • YENİDEN BAŞLAT Kurtarma işleminden çıkın ve cihazı normal şekilde yeniden başlatın.
  • APPLY_EXT, APPLY_CACHE, APPLY_ADB_SIDELOAD . Çeşitli yerlerden bir güncelleme paketi yükleyin. Ayrıntılar için bkz. Yandan Yükleme .
  • ÖNBELLEĞİ SİLİN . Yalnızca önbellek bölümünü yeniden biçimlendirin. Bu nispeten zararsız olduğundan onay gerekmez.
  • VERİLERİ SİLİN . 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ü aracılığıyla kurtarma işleminden 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 herhangi 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ğeri döndürmelisiniz; ancak şu anda dönüş değeri göz ardı edilmektedir. Başarılı veya başarısız olmanıza bakılmaksızın 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şturup döndüren make_device() işlevi için Recovery_ui.cpp dosyasının sonuna bazı metinler ekleyin:

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

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

Recovery_ui.cpp dosyasını tamamladıktan sonra oluşturun ve cihazınızdaki kurtarma işlemine bağlayın. Android.mk'de yalnızca bu C++ dosyasını içeren statik bir 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)

Daha sonra bu aygıtın 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ı arayüzü görüntüleri

Kurtarma kullanıcı arayüzü görüntülerden oluşur. İdeal durumda, kullanıcılar hiçbir zaman kullanıcı arayüzüyle etkileşime girmez: Normal bir güncelleme sırasında, telefon kurtarma işlemine başlar, kurulum ilerleme çubuğunu doldurur ve kullanıcıdan herhangi bir giriş olmadan yeni sisteme yeniden önyükleme yapar. Sistem güncelleme sorunu durumunda kullanıcı tarafından yapılabilecek tek işlem müşteri hizmetlerini aramaktır.

Yalnızca görüntüden oluşan bir arayüz, 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 üzeri

Android 5.0 ve üzeri kurtarma kullanıcı arayüzü iki ana resim kullanır: hata resmi 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 (Şekil 2'nin ezilmiş görünmesinin nedeni budur). Örneğin, 200x200 boyutunda yedi kareli bir animasyon için, ilk karenin 0, 7, 14, 21, ... satırları olduğu 200x1400 boyutunda tek bir görüntü oluşturun; ikinci çerçeve 1, 8, 15, 22, ... sıralarıdır; vb. Birleştirilmiş görüntü, animasyon karelerinin sayısını ve saniyedeki kare sayısını (FPS) belirten bir metin öbeği içerir. bootable/recovery/interlace-frames.py aracı bir dizi giriş karesi alır ve bunları kurtarma tarafından kullanılan gerekli kompozit görüntüde birleştirir.

Varsayılan görüntüler farklı yoğunluklarda mevcuttur ve bootable/recovery/res-$DENSITY/images (örneğin, bootable/recovery/res-hdpi/images ) konumunda bulunur. Kurulum 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 hareketli değildir; her zaman statik bir görüntüdür).

Android 4.x ve öncesi

Android 4.x ve önceki sürümlerde kurtarma kullanıcı arayüzü, hata görselini (yukarıda gösterilmektedir) ve yükleme animasyonunun yanı sıra birkaç katman görselini kullanır:

ota kurulumu sırasında gösterilen resim

Şekil 3. icon_installing.png

resim ilk katman olarak gösteriliyor

Şekil 4. icon-installing_overlay01.png

yedinci katman olarak gösterilen resim

Şekil 5. icon_installing_overlay07.png

Kurulum sırasında, ekran üstü görüntü, icon_installing.png görüntüsünün çizilmesi ve ardından kaplama çerçevelerinden birinin bunun üzerine uygun ofsetle çizilmesi yoluyla oluşturulur. Burada, kaplamanın temel görüntünün üstüne yerleştirildiği yeri vurgulamak için kırmızı bir kutu üst üste bindirilmiştir:

yükleme artı ilk yer paylaşımının kompozit görüntüsü

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

yükleme artı yedinci yer paylaşımının kompozit görüntüsü

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

Sonraki kareler, halihazırda orada olanın üzerine yalnızca bir sonraki kaplama görüntüsünün çizilmesiyle 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 uzaklıkları, ScreenRecoveryUI sınıfının üye değişkenleri tarafından ayarlanır. 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 betiği, gerekli uzaklıkların hesaplanması da dahil olmak üzere, bir dizi görüntü karesini kurtarmanın ihtiyaç duyduğu "temel görüntü + kaplama görüntüleri" biçimine dönüştürmeye yardımcı olabilir.

Varsayılan görüntüler bootable/recovery/res/images konumunda bulunur. Kurulum 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 hareketli değildir; her zaman statik bir görüntüdür).

Yerelleştirilmiş kurtarma metni

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

Kurtarma metin 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ı kurtarma işlemini manuel olarak başlattığında)

bootable/recovery/tools/recovery_l10n/ dosyasındaki Android uygulaması bir mesajın yerelleştirmelerini işler ve bileşik görüntüyü oluşturur. Bu uygulamanın kullanımına ilişkin ayrıntılar için bootable/recovery/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java adresindeki yorumlara bakın.

Kullanıcı kurtarma işlemini manuel olarak başlattığı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 eylem seçmesine olanak tanıyan 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ün birleştirilmesiyle oluşturulur:

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 gösterecek şekilde 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. %1'deki ilerleme çubuğu>

ilerleme çubuğu %10'da

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

ilerleme çubuğu %50'de

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

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

Not: Android 5.x'te, kurtarma işlemi için yerel ayar biliniyorsa ve sağdan sola (RTL) bir dil (Arapça, İbranice vb.) ise, ilerleme çubuğu sağdan sola doğru doldurulur.

Ekransız cihazlar

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

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 seviyeli kullanıcı arayüzü işlemlerini gerçekleştirmek için yöntemlere sahiptir. Uygun bir arayüz 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 ekranı" modunu hiç desteklemek istemezsiniz; ekranı hiçbir zaman açmayan veya bir menü öğesini 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 adresine bakın. RecoveryUI soyuttur (bazı yöntemler tamamen sanaldır ve alt sınıflar tarafından sağlanması gerekir), ancak anahtar girdilerin işlenmesini gerçekleştirecek kodu içerir. Cihazınızın anahtarları yoksa veya bunları farklı şekilde işlemek istiyorsanız bunu da geçersiz kılabilirsiniz.

Güncelleyici

Güncelleyici komut dosyanızdan çağrılabilecek kendi uzantı işlevlerinizi sağlayarak, güncelleme paketinin kurulumunda cihaza özel 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 dizi Expr* işaretçisinden oluşur. Dönüş değeri yeni tahsis edilen bir Value* dur.

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şlevinizin çağrıldığı sırada değerlendirilmemiştir; hangisinin kaç kez değerlendirileceğini işlevinizin mantığı belirler. Böylece kendi kontrol yapılarınızı uygulamak için uzantı işlevlerini kullanabilirsiniz. Bir Value* döndürerek bir Expr* bağımsız değişkenini değerlendirmek için Call Evaluate() . Evaluate() işlevi NULL değerini döndürürse, elinizde bulunan tüm kaynakları serbest bırakmalı ve hemen NULL değerini döndürmelisiniz (bu, düzenleme yığınının yukarıya doğru iptal edilmesine neden olur). Aksi takdirde, döndürülen Değerin sahipliğini alırsınız ve sonunda FreeValue() işlevinin çağrılmasından siz sorumlu olursunuz.

İşlevin iki bağımsız değişkene ihtiyacı olduğunu varsayalım: dize değerli bir anahtar ve blob değerli bir image . 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 olup olmadığını kontrol etmek ve önceden değerlendirilen bağımsız değişkenleri serbest bırakmak, birden fazla bağımsız değişken için sıkıcı olabilir. ReadValueArgs() işlevi bunu kolaylaştırabilir. Yukarıdaki kod yerine şunu da 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, dolayısıyla bunu burada yapmalısınız; başarısız olduğunda daha az spesifik bir hata mesajı üretme pahasına bunu bir if ifadesi ile yapmak daha uygundur. Ancak ReadValueArgs() değerlendirmelerden herhangi biri başarısız olursa, her bir argümanı değerlendirmeyi ve önceden değerlendirilen tüm argümanları serbest bırakmayı (aynı zamanda yararlı bir hata mesajı ayarlamayı) gerçekleştirir. Değişken sayıda bağımsız değişkeni değerlendirmek için ReadValueVarArgs() kolaylık işlevini kullanabilirsiniz (bir Value* dizisini döndürür).

Argümanları değerlendirdikten sonra fonksiyonun 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önüş değeri bir Value* nesnesi olmalıdır; bu nesnenin mülkiyeti arayan kişiye geçecektir. Arayan kişi, bu Value* tarafından işaret edilen tüm verilerin, özellikle de veri üyesinin sahipliğini alır.

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. Arayan kişi her ikisini de free() geri dönmek için sabit dizenin malloc'lanmış kopyasına sahip bir Value nesnesini malloc'lamalısınız. Argümanlarınızı değerlendirerek elde ettiğiniz nesneler üzerinde FreeValue() işlevini ç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;
}

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

   FreeValue(key);
    FreeValue(image);

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

İşlevleri edify 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 bir genişletme işlevini kaydetmek için RegisterFunction() öğesini çağırın. Geleneksel olarak, cihaza özgü işlevlere device . whatever Gelecekteki yerleşik işlevlerle çakışmaları önlemek için device . whatever eklendi.

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 makefile dosyasıdır; cihazınızda burada tanımlanmış her iki statik kitaplık da bulunabilir.)

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

Statik kütüphanenin adı, içinde bulunan Register_ libname fonksiyonunun adıyla eşleşmelidir.

LOCAL_MODULE := librecovery_updater_tardis
include $(BUILD_STATIC_LIBRARY)

Son olarak, kitaplığınızı çekecek kurtarma yapısını yapılandırın. Kitaplığınızı TARGET_RECOVERY_UPDATER_LIBS'ye ekleyin (birden fazla kitaplık içerebilir; hepsi kaydedilir). Kodunuz, kendileri düzenleme uzantıları olmayan diğer statik kitaplıklara bağlıysa (yani, Register_ libname işlevine sahip değillerse), (var olmayan) kayıt işlevlerini çağırmadan bunları güncelleyiciye bağlamak için bunları TARGET_RECOVERY_UPDATER_EXTRA_LIBS'de listeleyebilirsiniz. Örneğin, cihaza özel kodunuz verilerin sıkıştırmasını açmak için zlib'i kullanmak istiyorsa buraya libz'yi 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 komut dosyaları artık işlevinizi diğerleri gibi çağırabilir. Tardis cihazınızı yeniden programlamak için güncelleme komut dosyası ş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 oluşturmak için güncelleme paketinden çıkarılan bir dosyanın içeriğini bir blob 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 paket oluşturma araçlarının cihazınıza özel verileriniz hakkında bilgi sahibi olmasını ve uzantı işlevlerinize yapılan çağrıları içeren güncelleyici komut dosyalarını yayınlamasını sağlamaktır.

Öncelikle 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 dosyasında olduğunu varsayarsak, cihazınızın AndroidBoard.mk dosyasında aşağıdakileri bildirin:

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

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

Bunun yerine onu bir Android.mk dosyasına da koyabilirsiniz, ancak bu durumda bir cihaz kontrolü tarafından korunması gerekir, çünkü ağaçtaki tüm Android.mk dosyaları hangi cihaz oluşturulursa oluşturulsun yüklenir. (Ağacınız birden fazla cihaz içeriyorsa tardis.dat dosyasının yalnızca tardis cihazını oluştururken 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 nedenlerden dolayı radyo dosyaları adı verilir; cihazın radyosuyla (varsa) hiçbir ilgisi olmayabilir. Bunlar, derleme sisteminin OTA oluşturma araçları tarafından kullanılan .zip hedef dosyalarına kopyaladığı opak veri bloklarıdır. Bir derleme yaptığınızda tardis.dat, target-files.zip dosyasında RADIO/tardis.dat olarak depolanır. İstediğiniz sayıda dosya eklemek için add-radio-file birden çok kez çağırabilirsiniz.

Python modülü

Sürüm araçlarını genişletmek için, varsa araçların çağırabileceği bir Python modülü yazın (releasetools.py olarak adlandırılmalıdır). Ö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 örnekte, 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 bir zamanda çağrıldı. Burası cihazın mevcut durumu hakkında iddialarda bulunmak için iyi bir yerdir. Cihazda değişiklik yapan komut dosyası komutlarını yaymayın.
FullOTA_InstallBegin()
Cihaz durumuna ilişkin tüm iddialar geçtikten sonra ancak herhangi bir değişiklik yapılmadan önce çağrılır. Cihazdaki herhangi bir şey değiştirilmeden önce çalıştırılması gereken cihaza özel güncellemeler için komutlar verebilirsiniz.
FullOTA_InstallEnd()
Komut dosyası oluşturma işleminin sonunda, önyükleme ve sistem bölümlerini güncellemeye yönelik komut dosyası komutları yayınlandıktan sonra çağrılır. Ayrıca cihaza özel güncellemeler için ek komutlar da verebilirsiniz.
IncrementalOTA_Assertions()
FullOTA_Assertions() a benzer ancak artımlı bir güncelleme paketi oluşturulurken çağrılır.
IncrementalOTA_VerifyBegin()
Cihaz durumuna ilişkin tüm iddialar geçtikten sonra ancak herhangi bir değişiklik yapılmadan önce çağrılır. Cihazdaki herhangi bir şey değiştirilmeden önce çalıştırılması gereken cihaza özel güncellemeler için komutlar verebilirsiniz.
IncrementalOTA_VerifyEnd()
Doğrulama aşamasının sonunda, komut dosyası dokunacağı dosyaların beklenen başlangıç ​​içeriğine sahip olduğunu onaylamayı bitirdiğinde çağrılır. Bu noktada cihazda hiçbir şey değişmedi. 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 duruma sahip olduğu doğrulandıktan sonra çağrılır. Cihazdaki herhangi bir şey değiştirilmeden önce çalıştırılması gereken cihaza özel güncellemeler için komutlar verebilirsiniz.
IncrementalOTA_InstallEnd()
Tam OTA paketindeki karşılığına benzer şekilde bu, komut dosyası oluşturmanın sonunda, önyükleme ve sistem bölümlerini güncellemeye yönelik komut dosyası komutları yayınlandıktan sonra çağrılır. Ayrıca cihaza özel güncellemeler için ek komutlar da verebilirsiniz.

Not: Cihazın gücü kesilirse OTA kurulumu en baştan yeniden başlatılabilir. Bu komutların kısmen veya tamamen çalıştırıldığı cihazlarla baş etmeye hazır olun.

İşlevleri bilgi nesnelerine aktarma

İşlevleri, çeşitli yararlı öğeler içeren tek bir bilgi nesnesine aktarın:

  • bilgi.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 zaten aygıtta bulunan yapı).
  • info.target_zip . (Yalnızca Artımlı OTA'lar) Hedef hedef dosyalar .zip için zipfile.ZipFile nesnesi (artımlı paketin aygıta yerleştirdiği yapı).
  • info.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 ) öğesini kullanın.
  • info.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. Daha sonra verilen komutlarla karşılaşmaması için çıktı metninin noktalı virgülle bittiğinden emin olun.

Bilgi nesnesine ilişkin ayrıntılar için ZIP arşivlerine yönelik Python Software Foundation belgelerine bakın.

Modül konumunu belirtin

Cihazınızın Releasetools.py betiğinin konumunu BoardConfig.mk dosyanızda belirtin:

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

TARGET_RELEASETOOLS_EXTENSIONS := device/yoyodyne/tardis

TARGET_RELEASETOOLS_EXTENSIONS ayarlanmadıysa, varsayılan olarak $(TARGET_DEVICE_DIR)/../common dizini olur (bu örnekte device/yoyodyne/common ). Releasetools.py betiğinin konumunu açıkça tanımlamak en iyisidir. Tardis cihazını oluştururken, Releasetools.py betiği hedef dosyalar .zip dosyasına ( META/releasetools.py ) dahil edilir.

Yayınlama araçlarını ( img_from_target_files veya ota_from_target_files ) çalıştırdığınızda, hedef dosyalar .zip dosyasındaki yayın araçları.py betiği (varsa) Android kaynak ağacındaki betik yerine tercih edilir. Ayrıca, en yüksek önceliğe sahip olan -s (veya --device_specific ) seçeneğiyle cihaza özgü uzantıların yolunu açıkça belirtebilirsiniz. Bu, hataları düzeltmenize, sürüm araçları uzantılarında değişiklik yapmanıza ve bu değişiklikleri eski hedef dosyalara uygulamanıza olanak tanır.

Artık ota_from_target_files çalıştırdığınızda, cihaza özel modülü target_files .zip dosyasından otomatik olarak 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 belirtebilirsiniz.

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

Yandan yükleme mekanizması

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

Geçmişte, yandan yükleme, paketlerin cihazın SD kartından yüklenmesi yoluyla yapılıyordu; Önyükleme yapılmayan bir cihaz durumunda, paket başka bir bilgisayar kullanılarak SD karta yerleştirilebilir ve ardından SD kart cihaza takılabilir. Kurtarma, çıkarılabilir harici depolama alanı olmayan Android cihazlara uyum sağlamak için yandan yüklemeye yönelik iki ek mekanizmayı destekler: paketleri önbellek bölümünden yüklemek ve bunları adb kullanarak USB üzerinden yüklemek.

Her bir yan yükleme mekanizmasını çağırmak için cihazınızın Device::InvokeMenuItem() yöntemi aşağıdaki YerleşikAction değerlerini döndürebilir:

  • APPLY_EXT . Harici depolama biriminden ( /sdcard dizini) bir güncelleme paketini yandan yükleyin. Recovery.fstab'ınız /sdcard bağlama noktasını tanımlamalıdır. Bu, bir SD kartı /data (veya benzer bir mekanizma) bir SD kartı taklit eden cihazlarda kullanılamaz. /data genellikle şifrelenebileceği için kurtarma için mevcut değildir. Kurtarma kullanıcı arayüzü /sdcard içindeki .zip dosyaları menüsü görüntüler ve kullanıcının bir tane seçmesine izin verir.
  • Uygulama_cache . Bunun yerine /sdcard bir paket yüklemeye benzer şekilde /cache SDCARD'ın (her zaman kurtarma için mevcut olan ) kullanılması dışında. Normal sistemden, /cache yalnızca ayrıcalıklı kullanıcılar tarafından yazılabilir ve cihaz önyüklenemezse /cache dizini hiç yazılamaz (bu sınırlı yardımcı program mekanizmasını yapar).
  • Uygulama_adb_sideload . Kullanıcının bir USB kablosu ve ADB geliştirme aracı aracılığıyla cihaza bir paket göndermesine izin verir. Bu mekanizma çağrıldığında, Recovery, bağlı bir ana bilgisayardaki ADB'nin onunla konuşmasına izin vermek için ADBD Daemon'un kendi mini versiyonunu başlatır. Bu mini sürüm yalnızca tek bir komutu destekler: adb sideload filename . Adlandırılmış dosya ana makineden cihaza gönderilir, bu da tıpkı yerel depolamadaymış gibi doğrular ve yükler.

Birkaç uyarı:

  • Yalnızca USB taşımacılığı desteklenir.
  • Kurtarma işleminiz normal olarak ADBD çalıştırıyorsa (genellikle UserDebug ve Eng Builds için geçerlidir), cihaz ADB kenar yükü modundayken kapatılır ve ADB sideload bir paket almayı bitirdiğinde yeniden başlatılır. ADB sideload modundayken, sideload çalışması dışında ADB komutu yoktur ( logcat , reboot , push , pull , shell vb. Hepsi başarısız).
  • Cihazda ADB Sideload modundan çıkamazsınız. İptal etmek için, paket olarak /dev/null (veya geçerli bir paket olmayan başka bir şey) gönderebilirsiniz ve daha sonra cihaz bunu doğrulayamaz ve kurulum prosedürünü durduramaz. RecoveryUi uygulamasının CheckKey() yöntemi tuşlar için çağrılmaya devam edecektir, böylece cihazı yeniden başlatan ve ADB kenar yükü modunda çalışan bir anahtar dizi sağlayabilirsiniz.