APEX dosya biçimi

Android Pony EXpress (APEX) container biçimi Android 10'da kullanıma sunulmuş olup daha düşük düzeydeki sistem modüllerinin yükleme akışında kullanılır. Bu biçim, standart Android uygulama modeline uymayan sistem bileşenlerinin güncellenmesini kolaylaştırır. Bazı örnek bileşenler; yerel hizmetler ve kitaplıklar, donanım soyutlama katmanları (HAL'ler), çalışma zamanı (ART) ve sınıf kitaplıklarıdır.

"APEX" terimi, APEX dosyası için de kullanılabilir.

Arka plan

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

  • APK tabanlı modüller, başlatma sırasının başlarında kullanılamaz. Paket yöneticisi, uygulamalarla ilgili bilgilerin merkezi deposudur ve yalnızca önyükleme prosedürünün sonraki aşamaları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 olmayabilir.

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 için APEX geliştirilirken dikkate alınan alternatifler başlıklı makaleyi inceleyin.

APEX biçimi

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

APEX dosya biçimi

1. şekil. APEX dosya biçimi

En üst düzeyde, APEX dosyası, dosyaların sıkıştırılmadan 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 biçiminde bir ApexManifest protokol arabelleğidir.

AndroidManifest.xml dosyası, APEX dosyasının ADB, PackageManager ve paket yükleyici uygulamaları (ör. Play Store) 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 bilgiler genellikle apex_manifest.json bölümünde de yer alır.

APEX ile ilgilenen yeni kod ve sistemler için apex_manifest.json, AndroidManifest.xml yerine ö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ü, geri döngü cihazı aracılığıyla çalışma zamanında monte edilir. Özellikle karma ağacı ve meta veri bloğu, libavb kitaplığı kullanılarak oluşturulur. Dosya sistemi yükü ayrıştırılmıyor (çünkü resim yerinde monte edilebilir olmalıdır). Normal dosyalar apex_payload.img dosyasına dahil edilir.

apex_pubkey, dosya sistemi görüntüsü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 aynı 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ını kullanın:

  • com.android.*
    • AOSP APEX'leri için ayrılmıştır. Herhangi bir şirkete veya cihaza özel değildir.
  • com.<companyname>.*
    • Bir şirket için ayrılmıştır. Bu şirketin 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ğrulama, yükleme ve kaldırma işlemlerinden sorumlu bağımsız bir yerel işlemdir. Bu işlem başlatılır ve başlatma sırasının başında hazır olur. APEX dosyaları normalde cihazda /system/apex altında önceden yüklenmiş olarak bulunur. APEX yöneticisi, güncelleme yoksa 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 aracılığıyla indirilir.
  2. Paket yöneticisi, yükleme prosedürünü başlatır. Paket yöneticisi, dosyanın APEX olduğunu anladığında 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 yeniden başlatmada etkinleştirileceğini yansıtacak şekilde güncellenir.
  5. Yükleme isteğinde bulunan kullanıcı, paket doğrulama işlemi başarılı olduğunda yayın alır.
  6. Yüklemeye devam etmek için sistemin yeniden başlatılması gerekir.
  7. Bir sonraki başlatma işleminde APEX yöneticisi başlatılır, 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 geri döngü cihazı oluşturur.
    3. Geri döngü cihazının üzerinde 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ı bağlandığında APEX yöneticisi, diğer sistem bileşenlerinin yüklü APEX dosyalarıyla ilgili bilgileri sorgulaması için 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 tam olarak nereye monte edildiğini sorgulayabilir. Böylece, dosyalara erişilebilir.

APEX dosyaları, APK dosyalarıdır

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

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

Desteklenen dosya türleri

APEX biçimi şu 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üz tanımlarının ne kadar kararlı olduğuna bağlıdır.

İmzalama seçenekleri

APEX dosyaları iki şekilde imzalanır. İlk olarak, apex_payload.img (özellikle, apex_payload.img'ya 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ını 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. Bu kural hem derleme zamanında hem de çalışma zamanında zorunlu kılınır.

Dahili bölümlerde APEX

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

Yerleşik bir bölümde APEX varsa aynı paket adına ve sürüm koduna sahip bir APEX paketi sağlanarak APEX güncellenebilir. Yeni APEX, /data konumunda saklanır ve APK'lara benzer şekilde, yeni yüklenen sürüm, yerleşik bölümde bulunan sürümün yerini alır. Ancak APK'lardan farklı olarak, yeni yüklenen APEX sürümü yalnızca yeniden başlatma işleminden sonra etkinleştirilir.

Çekirdek gereksinimleri

Bir Android cihazda APEX ana hat modüllerini desteklemek için aşağıdaki Linux çekirdek özellikleri gerekir: loopback sürücüsü ve dm-verity. Loopback sürücüsü, 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 geri dö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ümü 4.4 veya daha yüksek olan cihazlarda desteklenir. Android 10 veya sonraki sürümlerle piyasaya sürülen yeni cihazlar, APEX modüllerini desteklemek için çekirdek sürümü 4.9 veya sonraki sürümleri 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 yapılması önemle tavsiye edilir. Aşağıda, çekirdek sürümü 4.4 için gerekli olan ayrı yamaların listesi verilmiştir.

  • UPSTREAM: loop: add ioctl for changing logical block size (4.4)
  • BACKPORT: block/loop: set hw_sectors (4.4)
  • UPSTREAM: loop: Add LOOP_SET_BLOCK_SIZE in compat ioctl (4.4)
  • ANDROID: mnt: Fix next_descendent (4.4)
  • ANDROID: mnt: remount should propagate to slaves of slaves (4.4)
  • ANDROID: mnt: Propagate remount correctly (4.4)
  • "ANDROID: dm verity: add minimum prefetch size" (ANDROID: dm verity: minimum önceden getirme boyutu ekle) geri alınacak (4.4)
  • YUKARI AKIŞ: döngü: uzaklık veya block_size değiştirilirse önbellekleri bırak (4.4)

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

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

Gerekli çekirdek yapılandırma seçenekleri

Aşağıdaki listede, Android 10'da kullanıma sunulan APEX modüllerini desteklemek için gereken temel yapılandırma koşulları gösterilmektedir. Yıldız işareti (*) ile işaretlenen öğeler, Android 9 ve önceki sürümlerdeki mevcut ş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ı parametreleriyle ilgili şartlar

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'e eşit veya daha küçük olmalıdır

APEX oluşturma

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

Geçişli 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 öğesine bağlıysa yalnızca libFoo, native_shared_libs özelliğinde listelendiğinde iki kitaplık da dahil edilir.

Birden fazla ABI'yi işleme

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 (ör. yalnızca 32 bit veya yalnızca 64 bit) sahip cihazları hedefliyorsa yalnızca ilgili ABI'ye sahip kitaplıklar yüklenir.

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

  • Cihaz yalnızca 32 bit ise ikilinin yalnızca 32 bitlik varyantı yüklenir.
  • Cihaz yalnızca 64 bit ise ikilinin yalnızca 64 bitlik varyantı yüklenir.

Yerel kitaplıkların ve ikili dosyaların ABI'leri üzerinde ayrıntılı kontrol sağlamak 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: Cihazın 64 bit ABI'siyle eşleşir ve 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ılandır.

java, libraries ve prebuilts özellikleri 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 imzası

Her APEX'i farklı anahtarlarla imzalayın. Yeni bir anahtar gerektiğinde herkese açık/özel anahtar çifti oluşturun ve apex_key modülü oluşturun. Anahtarı kullanarak APEX'i imzalamak için key özelliğini 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. Bir 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: bir kez mini dosya sistemi (apex_payload.img dosyası) için, bir kez de dosyanın tamamı için.

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

  • Ayarlanmadı: Değer ayarlanmamışsa APEX, PRODUCT_DEFAULT_DEV_CERTIFICATE konumundaki sertifikayla imzalanır. Hiçbir işaret ayarlanmamışsa yol varsayılan olarak build/target/product/security/testkey olur.
  • <name>: APEX, PRODUCT_DEFAULT_DEV_CERTIFICATE ile aynı dizinde bulunan <name> sertifikasıyla imzalanı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

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

adb install --force-non-staged apex_file_name

APEX kullanma

Yeniden başlatma işleminden sonra APEX, /apex/<apex_name>@<version> dizinine yüklenir. Aynı APEX'in birden fazla sürümü aynı anda monte edilebilir. Bağlama yolları arasında en son sürüme karşılık gelen yol, /apex/<apex_name> konumuna bağlama yolu olarak monte edilir.

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

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

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

Bir hizmeti APEX kaydıyla güncelleme

APEX kullanarak bir hizmeti güncellemek için:

  1. Sistem bölümündeki hizmeti güncellenebilir olarak işaretleyin. Seçeneği updatable 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. APEX'lerde işlem tetikleyicileri desteklenmez.

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

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

APEX dosyası 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 yalnızca

<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 mümkün olmaz veya pratik değildir. Örneğin, çekirdek, dosya sistemi görüntüsünü bir APEX'e yerleştirmek için çok önemli olan CONFIG_BLK_DEV_LOOP=Y olmadan oluşturulmuş olabilir.

Düzleştirilmiş APEX, eski çekirdekli cihazlarda etkinleştirilebilen özel olarak oluşturulmuş bir APEX'tir. Düzleştirilmiş bir 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, /system/apex/my.apex/lib/libFoo.so'ye yüklenir.my.apex

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'ye bağlanır.

İndirilen APEX'ler düzleştirilemediği için düzleştirilmiş APEX'ler, 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.

Varsayılan yapılandırma, düzleştirilmiş APEX'tir. Bu nedenle, cihazınızı APEX güncellemelerini desteklemek için açıkça düzleştirilmemiş APEX'ler oluşturacak şekilde yapılandırmadığınız sürece (yukarıda açıklandığı gibi) tüm APEX'ler varsayılan olarak düzleştirilir.

Bir cihazda düzleştirilmiş ve düzleştirilmemiş APEX'lerin birlikte kullanılması DESTEKLENMEZ. Bir cihazdaki APEX'lerin tamamı düzleştirilmemiş veya tamamı düzleştirilmiş olmalıdır. Bu durum, özellikle Mainline gibi projeler için önceden imzalanmış APEX önceden derlenmiş dosyaları gönderirken önemlidir. Önceden imzalanmamış (yani kaynaktan oluşturulmuş) APEX'ler de düzleştirilmemiş olmalı ve uygun anahtarlarla imzalanmalıdır. Cihaz, Bir hizmeti APEX ile güncelleme başlıklı makalede açıklandığı gibi updatable_apex.mk'ten devralmalıdır.

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

Android 12 ve sonraki sürümlerde, güncellenebilir APEX paketlerinin depolama alanındaki etkisini azaltmak için APEX sıkıştırma özelliği bulunur. APEX güncellemesi yüklendikten sonra, önceden yüklenmiş sürümü artık kullanılmasa da aynı miktarda alanı kaplamaya devam eder. Dolu alan kullanılamamaya devam eder.

APEX sıkıştırması, salt okunur bölümlerde (ör. /system bölümü) yüksek oranda sıkıştırılmış bir APEX dosyaları grubu kullanarak bu depolama alanı etkisini en aza indirir. Android 12 ve sonraki sürümlerde DEFLATE zip 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 aşamalarında bağlanması gereken Bootstrap APEX'leri.

  • Güncellenemeyen APEX'ler. Sıkıştırma yalnızca /data bölümüne güncellenmiş bir APEX sürümü yüklendiyse faydalı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ü (önceden yüklenmiş ve yükseltilmiş) her zaman etkinleştirdiğinden bunları sıkıştırmak değer katmaz.

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

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

Şemada, 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ış bir APEX dosyası, orijinal apex dosyasını 9 sıkıştırma seviyesiyle sıkıştırılmış biçimde içeren ve diğer dosyaların sıkıştırılmadan depolandığı bir zip dosyasıdır.

Bir APEX dosyası dört dosyadan oluşur:

  • original_apex: 9 sıkıştırma seviyesiyle sıkıştırılmamış Bu, orijinal ve 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'deki ilgili dosyaların kopyalarıdır.

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

Sıkıştırılmış APEX, apex_compression_tool.py aracını kullanarak oluşturulabilir. Bu araç, system/apex/tools konumunda bulunur.

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

Android.bp içinde bir APEX dosyasının sıkıştırılabilir olup olmadığı compressible özelliğiyle kontrol edilir:

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

Bir PRODUCT_COMPRESSED_APEX ürün işareti, kaynaktan oluşturulan bir sistem görüntüsünün sıkıştırılmış APEX dosyaları içerip içermemesi gerektiğini kontrol eder.

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

Derleme sistemi tarafından oluşturulan sıkıştırılmış APEX dosyaları .capex uzantısına sahiptir. Uzantı, 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.

Başlatma sırasında sıkıştırılmış bir APEX dosyasını etkinleştirme

Sıkıştırılmış bir APEX'in etkinleştirilebilmesi için içindeki original_apex dosyasının /data/apex/decompressed dizinine açılması gerekir. Elde edilen sıkıştırılmamış APEX dosyası, /data/apex/active dizinine sabit bağlantıyla bağlanır.

Yukarıda açıklanan süreci göstermek 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ı /data/apex/decompressed/com.android.foo@37.apex klasörüne 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. /data/apex/decompressed/com.android.foo@37.apex geçerliliğini sağlamak için doğrulama kontrolleri yapılır: apexd, /data/apex/decompressed/com.android.foo@37.apex içinde paketlenmiş ortak anahtarı kontrol ederek /system/apex/com.android.foo.capex içinde paketlenmiş olanla eşit olduğunu doğrular.
  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ı, OTA teslimatı ve uygulama üzerinde etkiler yaratır. Kablosuz güncelleme, cihazda etkin olan sürümden daha yüksek bir sürüm düzeyine sahip sıkıştırılmış bir APEX dosyası içerebileceğinden, kablosuz güncelleme 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 - Bir OTA paketindeki APEX dosyalarını açmak için gereken boyutu hesaplar. Bu, bir 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 alan ayırır.

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

APEX geliştirilirken dikkate alınan alternatifler

AOSP'nin APEX dosyası biçimini tasarlarken göz önünde bulundurduğu 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ü, olgun ve sağlam paket yönetim sistemleri bulunur. Ancak, yükleme işleminden sonra paketleri koruyamadıkları için APEX'te kullanılmazlar. Doğrulama yalnızca paketler yüklenirken gerçekleştirilir. Saldırganlar, yüklenen paketlerin bütünlüğünü fark edilmeden bozabilir. Bu, Android'de tüm sistem bileşenlerinin her G/Ç için bütünlüğü dm-verity ile korunan salt okunur dosya sistemlerinde depolandığı bir gerilemedir. Sistem bileşenlerinde herhangi bir kurcalama yasaklanmalı veya tespit edilebilir olmalıdır. Böylece, güvenliği ihlal edilmişse cihazın başlatılması reddedilebilir.

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

APEX kapsayıcısındaki dosyalar, dm-verity ile korunan yerleşik bölümlerde (ör. /system bölümü) bulunur. Bölümler bağlandıktan sonra bile dosyalarda değişiklik yapılması yasaktır. Dosyalara aynı düzeyde güvenlik sağlamak için bir APEX'teki tüm dosyalar, karma ağacı ve vbmeta tanımlayıcısıyla eşleştirilmiş 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.

Hatta /data bölümü, dm-crypt gibi şifreleme katmanlarıyla da korunur. Bu yöntem, kurcalamaya karşı bir miktar koruma sağlasa da asıl amacı bütünlük değil gizliliktir. Saldırgan /data bölümüne eriştiğinde başka koruma sağlanamaz. Bu durum, her sistem bileşeninin /system bölümünde olmasına kıyasla gerileme anlamına gelir. Bir APEX dosyasının içindeki karma ağacı, dm-verity ile birlikte aynı düzeyde içerik koruması sağlar.

/system yolundaki dosyaları /apex yoluna yönlendirme

APEX'te paketlenmiş sistem bileşeni dosyalarına /apex/<name>/lib/libfoo.so gibi yeni yollarla erişilebilir. Dosyalar /system bölümünün bir parçasıyken /system/lib/libfoo.so gibi yollarla erişilebiliyordu. 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ı (muhtemelen üst üste yerleştirilmiş) arttıkça performansın etkilenebileceği için dosyaları /system bölümüne yerleştirmemeye karar verdi.

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