APEX dosya biçimi

Android Pony EXpress (APEX) kapsayıcı formatı Android 10'da tanıtıldı ve alt düzey sistem modülleri için yükleme akışında kullanıldı. Bu format, standart Android uygulama modeline uymayan sistem bileşenlerinin güncellenmesini kolaylaştırır. Bazı örnek bileşenler arasında yerel hizmetler ve kitaplıklar, donanım soyutlama katmanları ( HAL'ler ), çalışma zamanı ( ART ) ve sınıf kitaplıkları yer alır.

"APEX" terimi aynı zamanda bir APEX dosyasına da işaret edebilir.

Arka plan

Android, paket yükleyici uygulamaları (Google Play Store uygulaması gibi) aracılığıyla standart uygulama modeline uyan modüllerin (örneğin hizmetler, etkinlikler) güncellemelerini desteklese de, daha düşük seviyeli işletim sistemi bileşenleri için benzer bir model kullanmanın aşağıdaki dezavantajları vardır:

  • APK tabanlı modüller, önyükleme sırasının başlarında kullanılamaz. Paket yöneticisi, uygulamalar hakkındaki bilgilerin merkezi deposudur ve yalnızca önyükleme prosedürünün daha sonraki bir aşamasında hazır hale gelen etkinlik yöneticisinden başlatılabilir.
  • APK formatı (özellikle manifest) Android uygulamaları için tasarlanmıştır ve sistem modülleri her zaman uygun değildir.

Tasarım

Bu bölümde APEX dosya formatının üst düzey tasarımı ve APEX dosyalarını yöneten bir hizmet olan APEX yöneticisi açıklanmaktadır.

APEX için bu tasarımın neden seçildiği hakkında daha fazla bilgi için bkz. APEX geliştirilirken dikkate alınan alternatifler .

APEX biçimi

Bu bir APEX dosyasının formatıdır.

APEX dosya formatı

Şekil 1. APEX dosya formatı

En üst düzeyde, APEX dosyası, dosyaların sıkıştırılmamış olarak depolandığı ve 4 KB sınırlarında bulunduğu bir zip dosyasıdır.

Bir APEX dosyasındaki dört dosya şunlardır:

  • apex_manifest.json
  • AndroidManifest.xml
  • apex_payload.img
  • apex_pubkey

apex_manifest.json dosyası, bir APEX dosyasını tanımlayan paket adını ve sürümünü içerir. Bu, JSON formatında bir ApexManifest protokol arabelleğidir.

AndroidManifest.xml dosyası, APEX dosyasının ADB, PackageManager ve paket yükleyici uygulamaları (Play Store gibi) gibi APK ile ilgili araçları ve altyapıyı kullanmasına olanak tanır. Örneğin, APEX dosyası, dosyadaki temel meta verileri incelemek için aapt gibi mevcut bir aracı kullanabilir. Dosya paket adı ve sürüm bilgilerini içerir. Bu bilgi genellikle apex_manifest.json dosyasında da mevcuttur.

APEX ile ilgilenen yeni kod ve sistemler için AndroidManifest.xml yerine apex_manifest.json önerilir. AndroidManifest.xml mevcut uygulama yayınlama araçları tarafından kullanılabilecek ek hedefleme bilgileri içerebilir.

apex_payload.img , dm-verity tarafından desteklenen bir ext4 dosya sistemi görüntüsüdür. Görüntü çalışma zamanında bir geridöngü aygıtı aracılığıyla bağlanır. Özellikle karma ağacı ve meta veri bloğu libavb kütüphanesi kullanılarak oluşturulur. Dosya sistemi verisi ayrıştırılmaz (çünkü görüntünün yerinde takılabilir olması gerekir). apex_payload.img dosyasının içinde normal dosyalar bulunur.

apex_pubkey , dosya sistemi görüntüsünü imzalamak için kullanılan genel anahtardır. Çalışma zamanında bu anahtar, indirilen APEX'in, yerleşik bölümlerde aynı APEX'i imzalayan aynı varlıkla imzalanmasını sağlar.

APEX adlandırma kuralları

Platform ilerledikçe yeni APEX'ler arasındaki adlandırma çakışmalarını önlemeye yardımcı olmak için aşağıdaki adlandırma yönergelerini kullanın:

  • com.android.*
    • AOSP APEX'ler için ayrılmıştır. Herhangi bir şirkete veya cihaza özgü değildir.
  • com.<companyname>.*
    • Bir şirkete rezerve edilmiştir. Potansiyel olarak söz konusu şirkete ait birden fazla cihaz tarafından kullanılmaktadır.
  • com.<companyname>.<devicename>.*
    • Belirli bir cihaza (veya cihazların alt kümesine) özgü APEX'ler için ayrılmıştır.

APEX yöneticisi

APEX yöneticisi (veya apexd ), APEX dosyalarını doğrulamaktan, yüklemekten ve kaldırmaktan sorumlu bağımsız bir yerel işlemdir. Bu işlem başlatılır ve önyükleme sırasının başlarında hazır olur. APEX dosyaları normalde cihaza /system/apex altında önceden yüklenmiştir. APEX yöneticisi, herhangi bir güncelleme mevcut değilse varsayılan olarak bu paketleri kullanır.

Bir APEX'in güncelleme sırası, PackageManager sınıfını kullanır ve aşağıdaki gibidir.

  1. Bir APEX dosyası bir paket yükleyici uygulaması, ADB veya başka bir kaynak aracılığıyla indirilir.
  2. Paket yöneticisi kurulum prosedürünü başlatır. Paket yöneticisi, dosyanın bir APEX olduğunu anladıktan sonra kontrolü APEX yöneticisine aktarır.
  3. APEX yöneticisi APEX dosyasını doğrular.
  4. APEX dosyası doğrulanırsa APEX yöneticisinin dahili veritabanı, APEX dosyasının bir sonraki önyüklemede etkinleştirileceğini yansıtacak şekilde güncellenir.
  5. Kurulum isteğinde bulunan kişi, başarılı paket doğrulamasının ardından bir yayın alır.
  6. Kuruluma devam etmek için sistemin yeniden başlatılması gerekir.
  7. Bir sonraki önyüklemede APEX yöneticisi başlar, dahili veritabanını okur ve listelenen her APEX dosyası için aşağıdakileri yapar:

    1. APEX dosyasını doğrular.
    2. APEX dosyasından bir geridöngü aygıtı oluşturur.
    3. Geridöngü aygıtının üstünde bir aygıt eşleyici blok aygıtı oluşturur.
    4. Cihaz eşleyici blok cihazını benzersiz bir yola bağlar (örneğin, /apex/ name @ ver ).

Dahili veritabanında listelenen tüm APEX dosyaları bağlandığında, APEX yöneticisi, diğer sistem bileşenlerinin, kurulu APEX dosyaları hakkındaki bilgileri sorgulaması için bir bağlayıcı hizmet sağlar. Örneğin, diğer sistem bileşenleri, cihazda yüklü olan APEX dosyalarının listesini sorgulayabilir veya belirli bir APEX'in monte edildiği tam yolu sorgulayabilir, böylece dosyalara erişilebilir.

APEX dosyaları APK dosyalarıdır

APEX dosyaları, bir AndroidManifest.xml dosyası içeren imzalı zip arşivleri (APK imza şemasını kullanan) olduğundan geçerli APK dosyalarıdır. Bu, APEX dosyalarının APK dosyaları için paket yükleyici uygulaması, imzalama yardımcı programı ve paket yöneticisi gibi altyapıyı kullanmasına olanak tanır.

Bir APEX dosyası içindeki AndroidManifest.xml dosyası minimum düzeydedir ve ayrıntılı hedefleme için paket name , versionCode ve isteğe bağlı targetSdkVersion , minSdkVersion ve maxSdkVersion oluşur. Bu bilgi, APEX dosyalarının paket yükleyici uygulamaları ve ADB gibi mevcut kanallar aracılığıyla teslim edilmesine olanak tanır.

Desteklenen dosya türleri

APEX formatı şu dosya türlerini destekler:

  • Yerel paylaşılan kütüphaneler
  • Yerel yürütülebilir dosyalar
  • JAR dosyaları
  • Veri dosyaları
  • Yapılandırma dosyaları

Bu, APEX'in bu dosya türlerinin tümünü güncelleyebileceği anlamına gelmez. Bir dosya türünün güncellenip güncellenemeyeceği platforma ve dosya türleri için arayüz tanımlarının ne kadar kararlı olduğuna bağlıdır.

İmzalama seçenekleri

APEX dosyaları iki şekilde imzalanır. Öncelikle apex_payload.img (özellikle apex_payload.img dosyasına eklenen vbmeta tanımlayıcı) dosyası bir anahtarla imzalanır. Daha sonra APEX'in tamamı APK imza şeması v3 kullanılarak imzalanır. Bu işlemde iki farklı anahtar kullanılır.

Cihaz tarafında vbmeta tanımlayıcısını imzalamak için kullanılan özel anahtara karşılık gelen bir ortak anahtar kurulur. APEX yöneticisi, kurulması istenen APEX'leri doğrulamak için ortak anahtarı kullanır. Her APEX'in farklı anahtarlarla imzalanması gerekir ve hem derleme hem de çalışma zamanında uygulanır.

Yerleşik bölümlerde APEX

APEX dosyaları, /system gibi yerleşik bölümlerde bulunabilir. Bölüm zaten dm-verity'nin üzerinde olduğundan APEX dosyaları doğrudan geri döngü aygıtının üzerine bağlanır.

Yerleşik bir bölümde bir APEX mevcutsa APEX, aynı paket adına ve sürüm kodundan büyük veya eşit olan bir APEX paketi sağlanarak güncellenebilir. Yeni APEX, /data dosyasında depolanır ve APK'lara benzer şekilde, yeni yüklenen sürüm, yerleşik bölümde zaten mevcut olan sürümü gölgede bırakır. Ancak APK'lardan farklı olarak APEX'in yeni yüklenen sürümü yalnızca yeniden başlatmanın ardından etkinleştirilir.

Çekirdek gereksinimleri

Bir Android cihazda APEX ana hat modüllerini desteklemek için aşağıdaki Linux çekirdek özellikleri gereklidir: geridöngü sürücüsü ve dm-verity. Geri döngü sürücüsü, dosya sistemi görüntüsünü bir APEX modülüne bağlar ve dm-verity, APEX modülünü doğrular.

APEX modüllerini kullanırken iyi sistem performansı elde etmede geridöngü sürücüsünün ve dm-verity'nin performansı önemlidir.

Desteklenen çekirdek sürümleri

APEX ana hat modülleri, çekirdek sürümleri 4.4 veya üzerini kullanan cihazlarda desteklenir. Android 10 veya üzeri sürümle başlatılan yeni cihazların, APEX modüllerini desteklemek için çekirdek sürümü 4.9 veya üzerini kullanması gerekir.

Gerekli çekirdek yamaları

APEX modüllerini desteklemek için gerekli çekirdek yamaları Android ortak ağacına dahil edilmiştir. Yamaların APEX'i desteklemesini sağlamak için Android ortak ağacının en son sürümünü kullanın.

Çekirdek sürümü 4.4

Bu sürüm yalnızca Android 9'dan Android 10'a yükseltilmiş ve APEX modüllerini desteklemek isteyen cihazlar için desteklenir. Gerekli yamaları almak için android-4.4 dalından aşağı birleştirme yapılması şiddetle tavsiye edilir. Aşağıda çekirdek 4.4 sürümü için gerekli bireysel yamaların listesi bulunmaktadır.

  • UPSTREAM: döngü: mantıksal blok boyutunu değiştirmek için ioctl ekleyin ( 4.4 )
  • BACKPORT: blok/döngü: hw_sectors'ı ayarla ( 4.4 )
  • UPSTREAM: döngü: uyumlu ioctl'ye LOOP_SET_BLOCK_SIZE ekleyin ( 4.4 )
  • ANDROID: mnt: next_descendent'i düzelt ( 4.4 )
  • ANDROID: mnt: remount kölelerin kölelerine yayılmalı ( 4.4 )
  • ANDROID: mnt: Yeniden montajı doğru şekilde yay ( 4.4 )
  • "ANDROID: dm verity: minimum önceden getirme boyutunu ekle" ifadesini geri alın ( 4.4 )
  • UPSTREAM: döngü: ofset veya blok_boyutu değiştirilirse önbellekleri bırakın ( 4.4 )

Çekirdek sürümleri 4.9/4.14/4.19

Çekirdek sürümleri 4.9/4.14/4.19 için gerekli yamaları almak için android-common şubesinden aşağı birleştirme yapın.

Gerekli çekirdek yapılandırma seçenekleri

Aşağıdaki liste, Android 10'da tanıtılan APEX modüllerini desteklemek için temel yapılandırma gereksinimlerini gösterir. Yıldız işareti (*) olan öğeler, Android 9 ve daha önceki sürümlerden mevcut gereksinimlerdir.

(*) CONFIG_AIO=Y # AIO support (for direct I/O on loop devices)
CONFIG_BLK_DEV_LOOP=Y # for loop device support
CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 # pre-create 16 loop devices
(*) CONFIG_CRYPTO_SHA1=Y # SHA1 hash for DM-verity
(*) CONFIG_CRYPTO_SHA256=Y # SHA256 hash for DM-verity
CONFIG_DM_VERITY=Y # DM-verity support

Çekirdek komut satırı parametre gereksinimleri

APEX'i desteklemek için çekirdek komut satırı parametrelerinin aşağıdaki gereksinimleri karşıladığından emin olun:

  • loop.max_loop ayarlanmamalıdır
  • loop.max_part <= 8 olmalıdır

Bir APEX oluşturun

Bu bölümde Android derleme sistemini kullanarak bir APEX'in nasıl oluşturulacağı açıklanmaktadır. Aşağıda apex.test adlı bir APEX için Android.bp örneği verilmiştir.

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    // libc.so and libcutils.so are included in the apex
    native_shared_libs: ["libc", "libcutils"],
    binaries: ["vold"],
    java_libs: ["core-all"],
    prebuilts: ["my_prebuilt"],
    compile_multilib: "both",
    key: "apex.test.key",
    certificate: "platform",
}

apex_manifest.json örneği:

{
  "name": "com.android.example.apex",
  "version": 1
}

file_contexts örneği:

(/.*)?           u:object_r:system_file:s0
/sub(/.*)?       u:object_r:sub_file:s0
/sub/file3       u:object_r:file3_file:s0

APEX'teki dosya türleri ve konumları

Dosya tipi APEX'teki konum
Paylaşılan kütüphaneler /lib ve /lib64 ( x86'da çevrilmiş kol için /lib/arm )
Yürütülebilir dosyalar /bin
Java kitaplıkları /javalib
Önceden oluşturulmuş yapılar /etc

Geçişli bağımlılıklar

APEX dosyaları otomatik olarak yerel paylaşılan kütüphanelerin veya yürütülebilir dosyaların geçişli bağımlılıklarını içerir. Örneğin, libFoo libBar bağlıysa, native_shared_libs özelliğinde yalnızca libFoo listelendiğinde iki kütüphane dahil edilir.

Birden fazla ABI'yi yönetin

Cihazın hem birincil hem de ikincil uygulama ikili arabirimleri (ABI'ler) için native_shared_libs özelliğini yükleyin. Bir APEX, tek bir ABI'ye sahip cihazları hedefliyorsa (yani yalnızca 32 bit veya yalnızca 64 bit), yalnızca karşılık gelen ABI'ye sahip kitaplıklar yüklenir.

binaries özelliğini yalnızca cihazın birincil ABI'si için aşağıda açıklandığı şekilde yükleyin:

  • Aygıt yalnızca 32 bit ise, ikili dosyanın yalnızca 32 bit sürümü yüklenir.
  • Cihaz yalnızca 64 bit ise ikili dosyanın yalnızca 64 bit sürümü yüklenir.

Yerel kitaplıkların ve ikili dosyaların ABI'leri üzerinde ayrıntılı denetim eklemek için multilib.[first|lib32|lib64|prefer32|both].[native_shared_libs|binaries] özelliklerini kullanın.

  • first : Cihazın birincil ABI'siyle eşleşir. Bu, ikili dosyalar için varsayılandır.
  • lib32 : Destekleniyorsa cihazın 32 bit ABI'siyle eşleşir.
  • lib64 : Desteklediği cihazın 64 bit ABI'sıyla eşleşir.
  • prefer32 : Destekleniyorsa cihazın 32 bit ABI'siyle eşleşir. 32 bit ABI desteklenmiyorsa 64 bit ABI ile eşleşir.
  • both : Her iki ABI ile de eşleşir. Bu native_shared_libraries için varsayılandır.

java , libraries ve prebuilts özellikler ABI'den bağımsızdır.

Bu örnek, 32/64'ü destekleyen ve 32'yi tercih etmeyen bir cihaz içindir:

apex {
    // other properties are omitted
    native_shared_libs: ["libFoo"], // installed for 32 and 64
    binaries: ["exec1"], // installed for 64, but not for 32
    multilib: {
        first: {
            native_shared_libs: ["libBar"], // installed for 64, but not for 32
            binaries: ["exec2"], // same as binaries without multilib.first
        },
        both: {
            native_shared_libs: ["libBaz"], // same as native_shared_libs without multilib
            binaries: ["exec3"], // installed for 32 and 64
        },
        prefer32: {
            native_shared_libs: ["libX"], // installed for 32, but not for 64
        },
        lib64: {
            native_shared_libs: ["libY"], // installed for 64, but not for 32
        },
    },
}

vbmeta imzalama

Her APEX'i farklı anahtarlarla imzalayın. Yeni bir anahtar gerektiğinde, genel-özel anahtar çifti oluşturun ve bir apex_key modülü oluşturun. Anahtarı kullanarak APEX'i imzalamak için key özelliğini kullanın. Genel anahtar, avb_pubkey adıyla APEX'e otomatik olarak dahil edilir.

# create an rsa key pair
openssl genrsa -out foo.pem 4096

# extract the public key from the key pair
avbtool extract_public_key --key foo.pem --output foo.avbpubkey

# in Android.bp
apex_key {
    name: "apex.test.key",
    public_key: "foo.avbpubkey",
    private_key: "foo.pem",
}

Yukarıdaki örnekte, genel anahtarın adı ( foo ), anahtarın kimliği haline gelir. APEX'i imzalamak için kullanılan anahtarın kimliği APEX'e yazılır. Çalışma zamanında apexd , cihazdaki aynı kimliğe sahip genel anahtarı kullanarak APEX'i doğrular.

APEX imzası

APEX'leri, APK'ları imzaladığınız şekilde imzalayın. APEX'leri iki kez imzalayın; bir kez mini dosya sistemi için ( apex_payload.img dosyası) ve bir kez de dosyanın tamamı için.

Dosya düzeyinde bir APEX imzalamak için certificate özelliğini şu üç yoldan biriyle ayarlayın:

  • Ayarlanmadı: Hiçbir değer ayarlanmadıysa APEX, PRODUCT_DEFAULT_DEV_CERTIFICATE konumunda bulunan sertifikayla imzalanır. Hiçbir bayrak ayarlanmadıysa yol varsayılan olarak build/target/product/security/testkey olur.
  • <name> : APEX, PRODUCT_DEFAULT_DEV_CERTIFICATE ile aynı dizinde bulunan <name> sertifikasıyla imzalanmıştır.
  • :<name> : APEX, <name> adlı Soong modülü tarafından tanımlanan sertifika ile imzalanır. Sertifika modülü aşağıdaki gibi tanımlanabilir.
android_app_certificate {
    name: "my_key_name",
    certificate: "dir/cert",
    // this will use dir/cert.x509.pem (the cert) and dir/cert.pk8 (the private key)
}

Bir APEX yükleyin

APEX yüklemek için ADB'yi kullanın.

adb install apex_file_name
adb reboot

apex_manifest.json dosyasında supportsRebootlessUpdate true olarak ayarlanmışsa ve şu anda yüklü olan APEX kullanılmıyorsa (örneğin, içerdiği hizmetler durdurulmuşsa), --force-non-staged bayrağıyla yeniden başlatmaya gerek kalmadan yeni bir APEX yüklenebilir .

adb install --force-non-staged apex_file_name

APEX kullanın

Yeniden başlatmanın ardından APEX, /apex/<apex_name>@<version> dizinine bağlanır. Aynı APEX'in birden fazla versiyonu aynı anda monte edilebilir. Bağlama yolları arasında en son sürüme karşılık gelen, /apex/<apex_name> konumunda bağlamayla bağlanır.

İstemciler, APEX'ten dosyaları okumak veya yürütmek için bağlamaya bağlı yolu kullanabilir.

APEX'ler genellikle şu şekilde kullanılır:

  1. Bir OEM veya ODM, cihaz gönderildiğinde /system/apex altına bir APEX'i önceden yükler.
  2. APEX'teki dosyalara /apex/<apex_name>/ yolu aracılığıyla erişilir.
  3. APEX'in güncellenmiş bir sürümü /data/apex yüklendiğinde yol, yeniden başlatmanın ardından yeni APEX'i işaret eder.

Bir hizmeti APEX ile güncelleme

APEX kullanarak bir hizmeti güncellemek için:

  1. Hizmeti sistem bölümünde güncellenebilir olarak işaretleyin. updatable seçeneğini hizmet tanımına ekleyin.

    /system/etc/init/myservice.rc:
    
    service myservice /system/bin/myservice
        class core
        user system
        ...
        updatable
    
  2. Güncellenen hizmet için yeni bir .rc dosyası oluşturun. Mevcut hizmeti yeniden tanımlamak için override seçeneğini kullanın.

    /apex/my.apex/etc/init.rc:
    
    service myservice /apex/my.apex/bin/myservice
        class core
        user system
        ...
        override
    

Hizmet tanımları yalnızca bir APEX'in .rc dosyasında tanımlanabilir. Eylem tetikleyicileri APEX'lerde desteklenmez.

Güncellenebilir olarak işaretlenen bir hizmet APEX'ler etkinleştirilmeden önce başlatılırsa başlatma, APEX'lerin etkinleştirilmesi tamamlanana kadar ertelenir.

Sistemi APEX güncellemelerini destekleyecek şekilde yapılandırın

APEX dosya güncellemelerini desteklemek için aşağıdaki sistem özelliğini true olarak ayarlayın.

<device.mk>:

PRODUCT_PROPERTY_OVERRIDES += ro.apex.updatable=true

BoardConfig.mk:
TARGET_FLATTEN_APEX := false

ya da sadece

<device.mk>:

$(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)

Düzleştirilmiş APEX

Eski cihazlar için, eski çekirdeğin APEX'i tam olarak destekleyecek şekilde güncellenmesi bazen imkansız veya mümkün olmayabilir. Örneğin çekirdek, dosya sistemi görüntüsünün bir APEX içine yerleştirilmesi için çok önemli olan CONFIG_BLK_DEV_LOOP=Y olmadan oluşturulmuş olabilir.

Düzleştirilmiş APEX, eski çekirdeğe sahip cihazlarda etkinleştirilebilen, özel olarak oluşturulmuş bir APEX'tir. Düzleştirilmiş bir APEX'teki dosyalar doğrudan yerleşik bölümün altındaki bir dizine yüklenir. Örneğin, düzleştirilmiş bir APEX'teki lib/libFoo.so my.apex /system/apex/my.apex/lib/libFoo.so konumuna yüklenir.

Düzleştirilmiş bir APEX'in etkinleştirilmesi döngü cihazını gerektirmez. /system/apex/my.apex dizininin tamamı doğrudan /apex/name@ver dizinine bağlanır.

Düzleştirilmiş APEX'ler, indirilen APEX'ler düzleştirilemediğinden, APEX'lerin güncellenmiş sürümleri ağdan indirilerek güncellenemez. Düzleştirilmiş APEX'ler yalnızca normal bir OTA aracılığıyla güncellenebilir.

Düzleştirilmiş APEX varsayılan yapılandırmadır. Bu, cihazınızı APEX güncellemelerini desteklemek üzere düzleştirilmemiş APEX'ler oluşturacak şekilde açıkça yapılandırmadığınız sürece tüm APEX'lerin varsayılan olarak düzleştirildiği anlamına gelir (yukarıda açıklandığı gibi).

Düzleştirilmiş ve düzleştirilmemiş APEX'lerin bir cihazda karıştırılması DESTEKLENMEZ. Bir cihazdaki APEX'lerin ya tamamı düzleştirilmemiş ya da tamamı düzleştirilmiş olmalıdır. Bu, özellikle Mainline gibi projeler için önceden imzalanmış APEX önceden oluşturulmuş sürümleri gönderilirken önemlidir. Önceden imzalanmamış (yani kaynaktan oluşturulmuş) APEX'ler de düzleştirilmemeli ve uygun anahtarlarla imzalanmalıdır. Cihaz , Bir hizmeti APEX ile güncelleme bölümünde açıklandığı gibi updatable_apex.mk miras almalıdır.

Sıkıştırılmış APEX'ler

Android 12 ve sonraki sürümler, güncellenebilir APEX paketlerinin depolama etkisini azaltmak için APEX sıkıştırma özelliğine sahiptir. APEX'e yönelik bir güncelleme yüklendikten sonra, önceden yüklenmiş sürümü artık kullanılmasa da aynı miktarda alanı kaplar. Bu işgal edilen alan kullanılamıyor.

APEX sıkıştırması, salt okunur bölümlerde ( /system bölümü gibi) yüksek düzeyde sıkıştırılmış APEX dosyaları kümesi kullanarak bu depolama etkisini en aza indirir. Android 12 ve sonraki sürümler DEFLATE zip sıkıştırma algoritmasını kullanır.

Sıkıştırma aşağıdakiler için optimizasyon sağlamaz:

  • Önyükleme sırasında çok erken monte edilmesi gereken Bootstrap APEX'ler.

  • Güncellenemeyen APEX'ler. Sıkıştırma yalnızca /data bölümüne APEX'in güncellenmiş bir sürümü yüklendiğinde faydalıdır. Güncellenebilir APEX'lerin tam listesi Modüler Sistem Bileşenleri sayfasında mevcuttur.

  • Dinamik paylaşılan kütüphaneler APEX'ler. apexd her zaman bu tür APEX'lerin her iki versiyonunu da etkinleştirdiğinden (önceden yüklenmiş ve yükseltilmiş), bunları sıkıştırmak değer katmaz.

Sıkıştırılmış APEX dosya formatı

Bu, sıkıştırılmış bir APEX dosyasının formatıdır.

Diagram shows the format of a compressed APEX file

Şekil 2. Sıkıştırılmış APEX dosya formatı

En üst düzeyde, sıkıştırılmış bir APEX dosyası, orijinal apex dosyasını sönük biçimde, sıkıştırma düzeyi 9 olan ve sıkıştırılmamış olarak saklanan diğer dosyaları içeren bir zip dosyasıdır.

Dört dosya bir APEX dosyasından oluşur:

  • original_apex : 9 sıkıştırma düzeyiyle söndürülmüş Bu orijinal, sıkıştırılmamış APEX dosyasıdır .
  • apex_manifest.pb : yalnızca depolanır
  • AndroidManifest.xml : yalnızca depolanır
  • apex_pubkey : yalnızca depolanır

apex_manifest.pb , AndroidManifest.xml ve apex_pubkey dosyaları, original_apex karşılık gelen dosyaların kopyalarıdır.

Sıkıştırılmış APEX oluşturun

Sıkıştırılmış APEX, system/apex/tools konumunda bulunan apex_compression_tool.py aracı kullanılarak oluşturulabilir.

APEX sıkıştırmasıyla ilgili çeşitli parametreler yapı sisteminde mevcuttur.

Android.bp bir APEX dosyasının sıkıştırılabilir olup olmadığı compressible özellik tarafından kontrol edilir:

apex {
    name: "apex.test",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    compressible: true,
}

PRODUCT_COMPRESSED_APEX ürün bayrağı, kaynaktan oluşturulan bir sistem görüntüsünün sıkıştırılmış APEX dosyaları içermesi gerekip gerekmediğini kontrol eder.

Yerel denemeler için OVERRIDE_PRODUCT_COMPRESSED_APEX= değerini true olarak ayarlayarak bir yapıyı APEX'leri sıkıştırmaya zorlayabilirsiniz.

Derleme sistemi tarafından oluşturulan sıkıştırılmış APEX dosyaları .capex uzantısına sahiptir. Uzantı, bir APEX dosyasının sıkıştırılmış ve sıkıştırılmamış sürümleri arasında ayrım yapmayı kolaylaştırır.

Desteklenen sıkıştırma algoritmaları

Android 12 yalnızca deflate-zip sıkıştırmasını destekler.

Önyükleme sırasında sıkıştırılmış bir APEX dosyasını etkinleştirin

Sıkıştırılmış bir APEX etkinleştirilmeden önce, içindeki original_apex dosyasının sıkıştırması /data/apex/decompressed dizinine açılır. Ortaya çıkan sıkıştırması açılmış APEX dosyası /data/apex/active dizinine sabit olarak bağlıdır.

Yukarıda açıklanan sürecin bir örneği olarak aşağıdaki örneği düşünün.

/system/apex/com.android.foo.capex versionCode 37 ile etkinleştirilen sıkıştırılmış bir APEX olarak düşünün.

  1. /system/apex/com.android.foo.capex içindeki original_apex dosyasının sıkıştırması /data/apex/decompressed/com.android.foo@37.apex olarak açılır.
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex , doğru bir SELinux etiketine sahip olduğunu doğrulamak için gerçekleştirilir.
  3. Geçerliliğini sağlamak için /data/apex/decompressed/com.android.foo@37.apex üzerinde doğrulama kontrolleri gerçekleştirilir: apexd /data/apex/decompressed/com.android.foo@37.apex içinde paketlenmiş genel anahtarı kontrol eder /system/apex/com.android.foo.capex içinde paketlenmiş olana eşit olduğunu doğrulayın.
  4. /data/apex/decompressed/com.android.foo@37.apex dosyası, /data/apex/active/com.android.foo@37.apex dizinine sabit bağlantılıdır.
  5. Sıkıştırılmamış APEX dosyaları için normal etkinleştirme mantığı /data/apex/active/com.android.foo@37.apex üzerinde gerçekleştirilir.

OTA ile etkileşim

Sıkıştırılmış APEX dosyalarının OTA dağıtımı ve uygulaması üzerinde etkileri vardır. Bir OTA güncellemesi, cihazda etkin olandan daha yüksek sürüm seviyesine sahip sıkıştırılmış bir APEX dosyası içerebileceğinden, bir OTA güncellemesini uygulamak için cihaz yeniden başlatılmadan önce belirli bir miktarda boş alan ayrılmalıdır.

OTA sistemini desteklemek için apexd şu iki bağlayıcı API'yi kullanıma sunar:

  • calculateSizeForCompressedApex - OTA paketindeki APEX dosyalarının sıkıştırmasını açmak için gereken boyutu hesaplar. Bu, bir OTA indirilmeden önce cihazın yeterli alana sahip olduğunu doğrulamak için kullanılabilir.
  • reserveSpaceForCompressedApex - OTA paketi içindeki sıkıştırılmış APEX dosyalarının sıkıştırmasını açmak için apexd tarafından gelecekte kullanılmak üzere diskte alan ayırır.

A/B OTA güncellemesi durumunda apexd , kurulum sonrası OTA rutininin bir parçası olarak arka planda sıkıştırmayı açmayı dener. Sıkıştırmayı açma işlemi başarısız olursa apexd , OTA güncellemesini uygulayan önyükleme sırasında sıkıştırmayı açma işlemini gerçekleştirir.

APEX geliştirilirken dikkate alınan alternatifler

APEX dosya formatını tasarlarken AOSP'nin dikkate aldığı bazı seçenekleri ve bunların neden dahil edildiğini veya hariç tutulduğunu burada bulabilirsiniz.

Düzenli paket yönetim sistemleri

Linux dağıtımları dpkg ve rpm gibi güçlü, olgun ve sağlam paket yönetim sistemlerine sahiptir. Ancak kurulumdan sonra paketleri koruyamadıkları için APEX'e uyarlanmadılar. Doğrulama yalnızca paketler yüklenirken gerçekleştirilir. Saldırganlar, kurulu paketlerin bütünlüğünü fark edilmeden bozabilirler. Bu, tüm sistem bileşenlerinin, her G/Ç için bütünlüğü dm-verity tarafından korunan salt okunur dosya sistemlerinde depolandığı Android için bir gerilemedir. Sistem bileşenlerine yapılacak herhangi bir müdahale ya yasaklanmalı ya da aygıtın tehlikeye atılması durumunda önyüklemeyi reddedebilmesi için tespit edilebilir olmalıdır.

bütünlük için dm-crypt

APEX kapsayıcısındaki dosyalar, dm-verity tarafından korunan yerleşik bölümlerden (örneğin, /system bölümü) gelir; burada bölümler bağlandıktan sonra bile dosyalarda herhangi bir değişiklik yapılması yasaktır. Dosyalara aynı düzeyde güvenlik sağlamak için APEX'teki tüm dosyalar, karma ağacı ve vbmeta tanımlayıcıyla eşleştirilen bir dosya sistemi görüntüsünde saklanır. Dm-verity olmadan, /data bölümündeki bir APEX, doğrulanıp yüklendikten sonra yapılan istenmeyen değişikliklere karşı savunmasızdır.

Aslında /data bölümü aynı zamanda dm-crypt gibi şifreleme katmanları tarafından da korunmaktadır. Bu, tahrifata karşı bir miktar koruma sağlasa da, asıl amacı bütünlük değil gizliliktir. Bir saldırgan /data bölümüne erişim kazandığında, daha fazla koruma olamaz ve bu da her sistem bileşeninin /system bölümünde olmasıyla karşılaştırıldığında bir gerilemedir. Bir APEX dosyasının içindeki karma ağacı, dm-verity ile birlikte aynı düzeyde içerik koruması sağlar.

Yolları /system'den /apex'e yönlendirin

APEX'te paketlenmiş sistem bileşeni dosyalarına /apex/<name>/lib/libfoo.so gibi yeni yollardan erişilebilir. Dosyalar /system bölümünün parçası olduğunda, bunlara /system/lib/libfoo.so gibi yollardan erişilebilir. Bir APEX dosyasının istemcisi (diğer APEX dosyaları veya platform) yeni yolları kullanmalıdır. Yol değişikliğinin bir sonucu olarak mevcut kodu güncellemeniz gerekebilir.

Yol değişikliğini önlemenin bir yolu, bir APEX dosyasındaki dosya içeriğini /system bölümüne yerleştirmek olsa da, Android ekibi, üst üste bindirilen dosya sayısı nedeniyle performansı etkileyebileceğinden, /system bölümündeki dosyaları üst üste bindirmemeye karar verdi ( hatta muhtemelen birbiri ardına istiflenmiş) arttı.

Diğer bir seçenek ise open , stat ve readlink gibi dosya erişim işlevlerini ele geçirmekti, böylece /system ile başlayan yollar /apex altındaki karşılık gelen yollara yeniden yönlendirildi. Android ekibi, yolları kabul eden tüm işlevleri değiştirmek mümkün olmadığından bu seçeneği göz ardı etti. Örneğin, bazı uygulamalar, işlevleri uygulayan Bionic'i statik olarak bağlar. Bu gibi durumlarda bu uygulamalar yönlendirilmez.