APEX dosyası biçimi

Android Pony EXpress (APEX) kapsayıcı biçimi Android 10'da kullanıma sunuldu ve alt düzey sistem modülleri için yükleme akışında kullanılır. Bu biçim, standart Android uygulama modeline uymayan sistem bileşenlerinin güncellenmesini kolaylaştırır. Yerel hizmetler ve kitaplıklar, donanım soyutlama katmanları (HAL'ler), çalışma zamanı (ART) ve sınıf kitaplıkları örnek bileşenlerden bazılarıdır.

"APEX" terimi, APEX dosyasını da ifade edebilir.

Arka plan

Android, standart uygulama modeline uyan modüllerin (ör. hizmetler, etkinlikler) paket yükleyici uygulamaları (Google Play Store uygulaması gibi) aracılığıyla güncellenmesini desteklese de daha düşük düzey işletim sistemi bileşenleri için benzer bir modelin kullanılması aşağıdaki dezavantajlara sahiptir:

  • APK tabanlı modüller, önyükleme sırasının başlarında kullanılamaz. Paket yöneticisi, uygulamalarla ilgili bilgilerin merkezi deposudur ve yalnızca önyükleme işleminin sonraki bir aşamasında hazır hale gelen etkinlik yöneticisinden başlatılabilir.
  • APK biçimi (ö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 biçiminin ve APEX dosyalarını yöneten bir hizmet olan APEX yöneticisinin üst düzey tasarımı açıklanmaktadır.

APEX için bu tasarımın neden seçildiği hakkında daha fazla bilgi edinmek isterseniz APEX geliştirirken değerlendirilen alternatifler başlıklı makaleyi inceleyin.

APEX biçimi

Bu, APEX dosyasının biçimidir.

APEX dosya biçimi

Şekil 1. APEX dosya biçimi

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

APEX dosyasında dört dosya bulunur:

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

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

AndroidManifest.xml dosyası, APEX dosyasının APK ile ilgili araçları ve altyapıyı (ör. ADB, PackageManager ve paket yükleyici uygulamaları (ör. Play Store)) 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ını ve sürüm bilgilerini içerir. Bu bilgiler genellikle apex_manifest.json'te de bulunur.

APEX ile çalışan yeni kod ve sistemler için AndroidManifest.xml yerine apex_manifest.json kullanılması ö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 döngü cihazı aracılığıyla monte edilir. Daha açık belirtmek gerekirse karma ağacı ve meta veri bloğu, libavb kitaplığı kullanılarak oluşturulur. Dosya sistemi yükü ayrıştırılmaz (çünkü görüntü yerinde monte edilebilir olmalıdır). Normal dosyalar apex_payload.img dosyasına dahil edilir.

apex_pubkey, dosya sistemi imajını imzalamak için kullanılan ortak anahtardır. Bu anahtar, çalışma zamanında indirilen APEX'in yerleşik bölümlerdeki aynı APEX'i imzalayan tüzel kişiyle imzalanmasını sağlar.

APEX adlandırma kuralları

Platform geliştikçe yeni APEX'ler arasında adlandırma çakışmalarını önlemek için aşağıdaki adlandırma kurallarına uyun:

  • com.android.*
    • AOSP APEX'leri için ayrılmıştır. Herhangi bir şirkete veya cihaza özel değildir.
  • com.<companyname>.*
    • Şirket için ayrılmış. Söz konusu şirketten birden fazla cihaz tarafından kullanılıyor olabilir.
  • com.<companyname>.<devicename>.*
    • Belirli bir cihaza (veya cihaz 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 başlatma sırasında erken hazır olur. APEX dosyaları genellikle cihaza /system/apex altında önceden yüklenmiştir. Güncelleme yoksa APEX yöneticisi 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. APEX dosyası, paket yükleyici uygulaması, ADB veya başka bir kaynak üzerinden indirilir.
  2. Paket yöneticisi, yükleme işlemini başlatır. Paket yöneticisi, dosyanın APEX olduğunu fark ettiğinde 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 açılışta etkinleştirileceğini yansıtacak şekilde güncellenir.
  5. Yükleme isteğinde bulunan kullanıcı, paket doğrulaması başarıyla tamamlandığında bir yayın alır.
  6. Yüklemeye devam etmek için sistemin yeniden başlatılması gerekir.
  7. APEX yöneticisi bir sonraki önyüklemede 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 döngü cihazı oluşturur.
    3. Döngüsel cihazın üzerine bir cihaz eşleyici blok cihazı oluşturur.
    4. Cihaz eşleyici blok cihazını benzersiz bir yola (örneğin, /apex/name@ver) bağlar.

Dahili veritabanında listelenen tüm APEX dosyaları monte edildiğinde APEX yöneticisi, diğer sistem bileşenlerinin yüklü APEX dosyaları hakkında bilgi sorgulamasına olanak tanıyan bir bağlayıcı hizmeti sağlar. Örneğin, diğer sistem bileşenleri cihaza yüklenen APEX dosyalarının listesini veya belirli bir APEX'in monte edildiği tam yolu sorgulayabilir. Böylece dosyalara erişilebilir.

APEX dosyaları APK dosyalarıdır

APEX dosyaları, AndroidManifest.xml dosyası içeren imzalanmış zip arşivleri (APK imza şeması kullanılarak) olduklarından geçerli APK dosyalarıdır. Bu sayede APEX dosyaları, APK dosyaları için altyapıyı (ör. paket yükleyici uygulaması, imzalama yardımcı programı ve paket yöneticisi) kullanabilir.

APEX dosyasındaki AndroidManifest.xml dosyası minimum düzeydedir ve name paketi, versionCode ve isteğe bağlı olarak ayrıntılı hedefleme için targetSdkVersion, minSdkVersion ve maxSdkVersion dosyalarından oluşur. Bu bilgiler, APEX dosyalarının paket yükleyici uygulamaları ve ADB gibi mevcut kanallar üzerinden dağıtılmasına olanak tanır.

Desteklenen dosya türleri

APEX biçimi aşağıdaki dosya türlerini destekler:

  • Yerel paylaşılan kitaplıklar
  • 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ürlerinin arayüzlerinin 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ısı) dosyası bir anahtarla imzalanır. Ardından, 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ı imzalamak için kullanılan özel anahtara karşılık gelen bir ortak anahtar yüklenir. APEX yöneticisi, yüklenmesi istenen APEX'leri doğrulamak için ortak anahtarı kullanır. Her APEX farklı anahtarlarla imzalanmalıdır ve hem derleme sırasında hem de çalışma zamanında zorunlu kılınmalıdır.

Yerleşik bölümlerde APEX

APEX dosyaları, /system gibi yerleşik bölümlerde bulunabilir. Bölüm zaten dm-verity üzerinde olduğundan APEX dosyaları doğrudan döngü cihazına monte edilir.

Yerleşik bir bölümde APEX varsa aynı paket adına ve sürüm kodundan büyük veya eşit bir APEX paketi sağlayarak APEX güncellenebilir. Yeni APEX, /data içinde depolanır ve APK'lara benzer şekilde, yeni yüklenen sürüm, yerleşik bölümde bulunan sürümü gölgeler. Ancak APK'ların aksine, APEX'in yeni yüklenen sürümü yalnızca yeniden başlatıldıktan sonra etkinleştirilir.

Çekirdek gereksinimleri

Android cihazlarda APEX ana hat modüllerini desteklemek için aşağıdaki Linux çekirdek özellikleri gereklidir: döngüsel sürücü ve dm-verity. Döngüsel sürücü, dosya sistemi görüntüsünü bir APEX modülüne monte eder ve dm-verity, APEX modülünü doğrular.

APEX modülleri kullanılırken iyi bir sistem performansı elde etmek için döngüsel sürücünün ve dm-verity'nin performansı önemlidir.

Desteklenen çekirdek sürümleri

APEX ana hat modülleri, 4.4 veya sonraki çekirdek sürümlerini kullanan cihazlarda desteklenir. Android 10 veya sonraki sürümlerin yüklü olduğu yeni cihazlar, APEX modüllerini desteklemek için 4.9 veya daha yeni bir çekirdek sürümü kullanmalıdır.

Gerekli çekirdek yamaları

APEX modüllerini desteklemek için gereken çekirdek yamaları, Android ortak ağacına dahil edilmiştir. APEX'i destekleyen yamaları almak 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ükseltilen ve APEX modüllerini desteklemek isteyen cihazlarda desteklenir. Gerekli yamaları almak için android-4.4 dalından aşağı birleştirme işlemi yapmanız önemle tavsiye edilir. Aşağıda, 4.4 çekirdek sürümü için gerekli tek tek yamaları görebilirsiniz.

  • UPSTREAM: loop: mantıksal blok boyutunu değiştirmek için ioctl ekleyin (4.4)
  • BACKPORT: block/loop: set hw_sectors (4.4)
  • UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl (4.4)
  • ANDROID: mnt: next_descendent'i düzeltin (4.4)
  • ANDROID: mnt: remount should propagate to slaves of slaves (4.4)
  • ANDROID: mnt: Yeniden bağlama işlemini doğru şekilde yayma (4.4)
  • "ANDROID: dm verity: add minimum prefetch size" (4.4) özelliğini geri alma
  • UPSTREAM: loop: offset veya block_size değişirse önbellekleri bırak (4.4)

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

4.9/4.14/4.19 çekirdek sürümleri için gerekli yamaları almak üzere android-common dalından aşağı doğru birleştirme yapın.

Zorunlu çekirdek yapılandırma seçenekleri

Aşağıdaki listede, Android 10'da kullanıma sunulan APEX modüllerini desteklemek için temel yapılandırma gereksinimleri gösterilmektedir. Yıldız işareti (*) içeren öğeler, Android 9 ve önceki sürümlerde geçerli olan şartlardır.

(*) 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ı parametresi koşulları

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

  • loop.max_loop ayarlanMAMALIDIR
  • loop.max_part 8'den küçük olmalıdır

APEX oluşturma

Bu bölümde, Android derleme sistemini kullanarak APEX'in nasıl derleneceği 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 türü APEX'teki konum
Paylaşılan kitaplıklar /lib ve /lib64 (x86'ta çevrilmiş ARM için /lib/arm)
Yürütülebilir dosyalar /bin
Java kitaplıkları /javalib
Hazır sistemler /etc

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

APEX dosyaları, yerel paylaşılan kitaplıkların veya yürütülebilir dosyaların geçişli bağımlılıklarını otomatik olarak içerir. Örneğin, libFoo, libBar'e bağlıysa native_shared_libs mülkünde yalnızca libFoo listelendiğinde iki kitaplık da dahil edilir.

Birden fazla ABI'yi işleme

Cihazın hem birincil hem de ikincil uygulama ikili arayüzleri (ABI'leri) için native_shared_libs mülkünü yükleyin. Bir APEX tek bir ABI'ye sahip cihazları (ör. yalnızca 32 bit veya yalnızca 64 bit) hedefliyorsa yalnızca ilgili ABI'ye sahip kitaplıklar yüklenir.

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

  • Cihaz yalnızca 32 bit ise ikili dosyanın yalnızca 32 bit varyantı yüklenir.
  • Cihaz yalnızca 64 bit ise ikili dosyanın yalnızca 64 bit varyantı yüklenir.

Yerel kitaplıkların ve ikili dosyaların ABI'leri üzerinde ayrıntılı kontrol 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ılan ayardır.
  • lib32: Destekleniyorsa cihazın 32 bit ABI'siyle eşleşir.
  • lib64: Cihazın 64 bit ABI'siyle eşleşiyor, desteklenir.
  • 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ılan ayardır.

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

Bu örnek, 32/64 bit'i destekleyen ve 32 bit'i 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 imzası

Her APEX'i farklı anahtarlarla imzalayın. Yeni bir anahtar gerektiğinde herkese açık-özel anahtar çifti oluşturun ve bir apex_key modülü oluşturun. Anahtarı kullanarak APEX'i imzalamak için key mülkünü kullanın. Ortak 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, herkese açık anahtarın adı (foo) anahtarın kimliği olur. 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 bir ortak anahtar kullanarak APEX'i doğrular.

APEX imzalama

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

Bir APEX'i dosya düzeyinde imzalamak için certificate mülkünü aşağıdaki üç yöntemden biriyle ayarlayın:

  • Ayarlanmadı: Herhangi bir değer ayarlanmazsa APEX, PRODUCT_DEFAULT_DEV_CERTIFICATE adresinde bulunan sertifikayla imzalanır. Hiçbir işaret 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 sertifikayla 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)
}

APEX yükleme

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

adb install apex_file_name
adb reboot

supportsRebootlessUpdate, apex_manifest.json içinde true olarak ayarlanmışsa ve şu anda yüklü olan APEX kullanılmamışsa (örneğin, içerdiği hizmetler durdurulmuşsa) yeni bir APEX, --force-non-staged işaretiyle yeniden başlatılmadan yüklenebilir.

adb install --force-non-staged apex_file_name

APEX kullanma

Yeniden başlatıldıktan sonra APEX, /apex/<apex_name>@<version> dizinine eklenir. Aynı APEX'in birden fazla sürümü aynı anda monte edilebilir. Bağlantı yolları arasında en son sürüme karşılık gelen yol, /apex/<apex_name> adresinde bağlanma bağlantısı ile monte edilir.

İstemciler, APEX'teki dosyaları okumak veya yürütmek için bağlanmış yolu kullanabilir.

APEX'ler genellikle aşağıdaki şekilde kullanılır:

  1. OEM veya ODM, cihaz gönderilirken /system/apex altında bir APEX ön yükler.
  2. APEX'teki dosyalara /apex/<apex_name>/ yolu üzerinden erişilir.
  3. /data/apex'e APEX'in güncellenmiş bir sürümü yüklendiğinde, yeniden başlatma işleminden sonra yol yeni APEX'i gösterir.

APEX ile bir hizmeti güncelleme

Bir hizmeti APEX kullanarak güncellemek için:

  1. Sistem bölümündeki hizmeti 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. İşlem tetikleyicileri APEX'lerde desteklenmez.

Güncelleme yapılabilir olarak işaretlenmiş bir hizmet, APEX'ler etkinleştirilmeden önce başlarsa APEX'lerin etkinleştirilmesi tamamlanana kadar başlatma işlemi ertelenir.

Sistemi APEX güncellemelerini destekleyecek şekilde yapılandırma

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

veya

<device.mk>:

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

Düzleştirilmiş APEX

Eski cihazlarda, eski çekirdeği APEX'i tam olarak destekleyecek şekilde güncellemek bazen imkansız veya uygulanamaz olabilir. Örneğin, çekirdek CONFIG_BLK_DEV_LOOP=Y olmadan oluşturulmuş olabilir. Bu, dosya sistemi imajının bir APEX'e monte edilmesi için çok önemlidir.

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

Düzleştirilmiş bir APEX'in etkinleştirilmesi, döngü cihazını içermez. /system/apex/my.apex dizininin tamamı doğrudan /apex/name@ver'a bağlanarak monte edilir.

İndirilen APEX'ler düzleştirilemediği için düzleştirilmiş APEX'ler, APEX'lerin güncel 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 için yukarıda açıklandığı şekilde 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.

Bir cihazda düzleştirilmiş ve düzleştirilmemiş APEX'lerin karıştırılması DESTEKLENMEZ. Bir cihazdaki APEX'lerin tümü düzleştirilmemiş veya tümü düzleştirilmiş olmalıdır. Bu, özellikle Mainline gibi projeler için önceden imzalanmış APEX hazır derlemeleri gönderirken önemlidir. Önceden imzalanmamış (yani kaynaktan oluşturulmuş) APEX'ler de düzleştirilmemiş ve uygun anahtarlarla imzalanmamış olmalıdır. Cihaz, APEX ile bir hizmeti güncelleme bölümünde açıklandığı gibi updatable_apex.mk öğesinden devralınmalıdır.

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

Android 12 ve sonraki sürümlerde, güncellenebilir APEX paketlerinin depolama üzerindeki etkisini azaltmak için APEX sıkıştırması bulunur. APEX'te güncelleme yapıldıktan sonra, önceden yüklenmiş sürümü artık kullanılmasa da aynı miktarda yer kaplar. Bu dolu alan kullanılamaz.

APEX sıkıştırması, salt okunur bölümlerde (/system bölümü gibi) yüksek oranda sıkıştırılmış bir APEX dosyası grubu kullanarak bu depolama alanını en aza indirir. Android 12 ve sonraki sürümlerde DEFLATE sıkıştırma algoritması kullanılır.

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

  • Önyükleme sırasının çok erken bir aşamasında monte edilmesi gereken önyükleme APEX'leri.

  • Güncellenemeyecek APEX'ler. Sıkıştırma yalnızca /data bölümüne APEX'in güncellenmiş bir sürümü yüklüyse yararlıdır. Güncellenebilir APEX'lerin tam listesini Modüler Sistem Bileşenleri sayfasında bulabilirsiniz.

  • Dinamik paylaşılan kitaplık APEX'leri. apexd, bu tür APEX'lerin her iki sürümünü de (önceden yüklenmiş ve yükseltilmiş) her zaman etkinleştirdiğinden, bunları sıkıştırmak değer sağlamaz.

Sıkıştırılmış APEX dosya biçimi

Bu, sıkıştırılmış bir APEX dosyasının biçimidir.

Diyagramda, sıkıştırılmış bir APEX dosyasının biçimi gösterilmektedir

Şekil 2. Sıkıştırılmış APEX dosya biçimi

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

APEX dosyası dört dosyadan oluşur:

  • original_apex: 9 sıkıştırma düzeyiyle sönümlendirilmiş 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'daki ilgili dosyaların kopyalarıdır.

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

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

Derleme sisteminde APEX sıkıştırmasıyla ilgili çeşitli parametreler bulunur.

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

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

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

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

Derleme sistemi tarafından oluşturulan sıkıştırılmış APEX dosyalarının uzantısı .capex'tür. Uzatma, APEX dosyasının sıkıştırılmış ve sıkıştırılmamış sürümlerini ayırt etmeyi kolaylaştırır.

Desteklenen sıkıştırma algoritmaları

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

Açılış sırasında sıkıştırılmış bir APEX dosyasını etkinleştirme

Sıkıştırılmış bir APEX etkinleştirilmeden önce içindeki original_apex dosyası /data/apex/decompressed dizininde sıkıştırılır. Sıkıştırılmış APEX dosyasının sıkıştırması kaldırılarak oluşturulan dosya, /data/apex/active dizine sabit bağlantıyla bağlanır.

Yukarıda açıklanan süreci açıklamak için aşağıdaki örneği inceleyin.

/system/apex/com.android.foo.capex, versionCode 37 ile etkinleştirilen sıkıştırılmış bir APEX olarak kabul edilir.

  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 içinde kaldırılır.
  2. restorecon /data/apex/decompressed/com.android.foo@37.apex doğru SELinux etiketine sahip olduğunu doğrulamak için gerçekleştirilir.
  3. /data/apex/decompressed/com.android.foo@37.apex'ün geçerliliğini sağlamak için doğrulama kontrolleri yapılır: apexd, /data/apex/decompressed/com.android.foo@37.apex'te paketlenmiş ortak anahtarı /system/apex/com.android.foo.capex'de paketlenmiş anahtarla eşleşip eşleşmediğini doğrulamak için kontrol eder.
  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 yayını ve uygulaması üzerinde etkileri vardır. OTA güncellemesi, cihazda etkin olandan daha yüksek sürüm düzeyine sahip sıkıştırılmış bir APEX dosyası içerebileceğinden, OTA güncellemesinin uygulanması için cihaz yeniden başlatılmadan önce belirli miktarda boş alan ayrılmalıdır.

OTA sistemini desteklemek için apexd aşağıdaki iki bağlayıcı API'sini gösterir:

  • calculateSizeForCompressedApex: OTA paketindeki APEX dosyalarının sıkıştırmasını açmak için gereken boyutu hesaplar. Bu yöntem, OTA indirilmeden önce cihazda yeterli alan olup olmadığını doğrulamak için kullanılabilir.
  • reserveSpaceForCompressedApex: OTA paketindeki 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 yer ayırır.

A/B OTA güncellemesi söz konusu olduğunda apexd, yükleme sonrası OTA rutini kapsamında arka planda sıkıştırma işlemini gerçekleştirmeye çalışır. Sıkıştırma açma işlemi başarısız olursa apexd, OTA güncellemesini uygulayan önyükleme sırasında sıkıştırma açma işlemini gerçekleştirir.

APEX geliştirirken dikkate alınan alternatifler

AOSP'nin APEX dosya biçimini tasarlarken değerlendirdiği bazı seçenekler ve bunların neden dahil edildiği veya hariç tutulduğu aşağıda açıklanmıştır.

Normal paket yönetim sistemleri

Linux dağıtımlarında dpkg ve rpm gibi güçlü, gelişmiş ve sağlam paket yönetim sistemleri bulunur. Ancak yükleme sonrasında paketleri koruyamadıkları için APEX için benimsenmediler. Doğrulama yalnızca paketler yüklenirken yapılır. Saldırganlar, yüklü paketlerin bütünlüğünü fark edilmeden bozabilir. Bu, tüm sistem bileşenlerinin, bütünlüğü her G/Ç için dm-verity tarafından korunan salt okunur dosya sistemlerinde depolandığı Android için bir gerilemedir. Sistem bileşenlerinde yapılan tüm değişiklikler yasaklanmalı veya cihazın güvenliği ihlal edildiğinde cihazın başlatılmasını reddedebileceği şekilde algılanabilir olmalıdır.

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

APEX kapsayıcısındaki dosyalar, dm-verity ile korunan yerleşik bölümlerden (ör. /system bölümü) alınır. Bu bölümler monte edildikten 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ısı ile eşleştirilen bir dosya sistemi görüntüsünde depolanır. dm-verity olmadan, /data bölümündeki bir APEX, doğrulandıktan ve yüklendikten sonra yapılan istenmeyen değişikliklere karşı savunmasızdır.

/data bölümü, dm-crypt gibi şifreleme katmanlarıyla da korunur. Bu, bozulmaya karşı bir düzeyde koruma sağlasa da birincil amacı bütünlük değil gizliliktir. Bir saldırgan /data bölümüne eriştiğinde başka bir koruma olamaz. Bu da, tüm sistem bileşenlerinin /system bölümünde bulunduğu duruma kıyasla bir gerilemedir. APEX dosyasındaki karma ağacı, dm-verity ile birlikte aynı düzeyde içerik koruması sağlar.

/system yolunu /apex'e yönlendirme

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

Yol değişikliğini önlemenin bir yolu, APEX dosyasındaki dosya içeriklerini /system bölümüne yerleştirmektir. Ancak Android ekibi, yerleştirilen dosya sayısı arttıkça (hatta birbirinin üzerine yığılabilir) performansı etkileyebileceği için dosyaları /system bölümüne yerleştirmemeye karar verdi.

Diğer bir seçenek de open, stat ve readlink gibi dosya erişimi işlevlerini ele geçirmekti. Böylece /system ile başlayan yollar, /apex altındaki ilgili yollarına yönlendiriliyordu. Android ekibi, yol kabul eden tüm işlevleri değiştirmenin mümkün olmaması nedeniyle bu seçeneği reddetti. Örneğin, bazı uygulamalar işlevleri uygulayan Bionic'i statik olarak bağlar. Bu tür durumlarda, söz konusu uygulamalar yönlendirilmez.