Tedarikçi APEX

Alt düzey Android OS modüllerini paketlemek ve yüklemek için APEX dosya biçimini kullanabilirsiniz. Yerel hizmetler ve kitaplıklar, HAL uygulamaları, donanım yazılımı, yapılandırma dosyaları gibi bileşenlerin bağımsız olarak derlenmesine ve yüklenmesine olanak tanır.

Tedarikçi APEX'leri, derleme sistemi tarafından /vendor bölümüne otomatik olarak yüklenir ve diğer bölümlerdeki APEX'ler gibi apexd tarafından çalışma zamanında etkinleştirilir.

Kullanım örnekleri

Tedarikçi firma resimlerinin modülerleştirilmesi

APEX'ler, tedarikçi firma resimlerinde özellik uygulamalarının doğal bir şekilde gruplandırılmasını ve modülerleştirilmesini sağlar.

Tedarikçi firma resimleri, bağımsız olarak oluşturulmuş tedarikçi firma APEX'lerinin bir kombinasyonu olarak oluşturulduğunda cihaz üreticileri, cihazlarında istedikleri tedarikçi firma uygulamalarını kolayca seçebilir. Üreticiler, sağlanan APEX'lerden hiçbiri ihtiyaçlarına uymuyorsa veya yepyeni özel donanımlara sahiplerse yeni bir tedarikçi APEX'i bile oluşturabilirler.

Örneğin, bir OEM cihazını AOSP kablosuz bağlantı uygulama APEX'i, SoC bluetooth uygulama APEX'i ve özel OEM telefon uygulama APEX'iyle oluşturmayı seçebilir.

Tedarikçi firma APEX'leri olmadan, tedarikçi firma bileşenleri arasında çok fazla bağımlılık içeren bir uygulamanın dikkatli bir şekilde koordine edilmesi ve izlenmesi gerekir. Tüm bileşenler (yapılandırma dosyaları ve ek kitaplıklar dahil), özellik içi iletişimin herhangi bir noktasında net bir şekilde tanımlanmış arayüzlere sahip APEX'lere sarmalanarak farklı bileşenler birbirinin yerine kullanılabilir hale gelir.

Geliştirici iterasyonu

Tedarikçi APEX'leri, bir tedarikçi APEX'inin içine WiFi HAL gibi bir özellik uygulamasının tamamını paketleyerek tedarikçi modülleri geliştirirken geliştiricilerin daha hızlı iterasyon yapmasına yardımcı olur. Geliştiriciler daha sonra tedarikçi firma imajının tamamını yeniden oluşturmak yerine değişiklikleri test etmek için tedarikçi firma APEX'ini oluşturup tek tek gönderebilir.

Bu, esas olarak tek bir özellik alanında çalışan ve yalnızca bu özellik alanında iterasyon yapmak isteyen geliştiriciler için geliştirici iterasyon döngüsünü basitleştirir ve hızlandırır.

Bir özellik alanının APEX'te doğal olarak gruplandırılması, söz konusu özellik alanındaki değişiklikleri oluşturma, yayınlama ve test etme sürecini de basitleştirir. Örneğin, bir APEX'i yeniden yüklediğinizde APEX'in içerdiği tüm paketlenmiş kitaplıklar veya yapılandırma dosyaları otomatik olarak güncellenir.

Bir özellik alanını APEX'te gruplandırmak, kötü cihaz davranışı gözlemlendiğinde hata ayıklama veya geri alma işlemlerini de kolaylaştırır. Örneğin, yeni bir derlemede telefon işlevi düzgün çalışmıyorsa geliştiriciler, cihaza eski bir telefon işlevi APEX'i yüklemeyi (tam derlemeyi yüklemeye gerek kalmadan) deneyip iyi davranışın geri dönüp dönmediğini görebilir.

Örnek iş akışı:

# Build the entire device and flash. OR, obtain an already-flashed device.
source build/envsetup.sh && lunch oem_device-userdebug
m
fastboot flashall -w

# Test the device.
... testing ...

# Check previous behavior using a vendor APEX from one week ago, downloaded from
# your continuous integration build.
... download command ...
adb install <path to downloaded APEX>
adb reboot
... testing ...

# Edit and rebuild just the APEX to change and test behavior.
... edit APEX source contents ...
m <apex module name>
adb install out/<path to built APEX>
adb reboot
... testing ...

Örnekler

Temel Bilgiler

Cihaz gereksinimleri, dosya biçimi ayrıntıları ve yükleme adımları dahil olmak üzere genel APEX bilgileri için ana APEX Dosya Biçimi sayfasına bakın.

Android.bp içinde vendor: true mülkünün ayarlanması, APEX modülünü tedarikçi APEX'e dönüştürür.

apex {
  ..
  vendor: true,
  ..
}

İkili dosyalar ve paylaşılan kitaplıklar

APEX'ler, sabit arayüzleri olmadığı sürece APEX yükü içinde geçişli bağımlılıklar içerir.

Satıcı APEX bağımlılıkları için kararlı yerel arayüzler arasında cc_library ile stubs ve LLNDK kitaplıkları bulunur. Bu bağımlılıklar paketlemeye dahil edilmez ve APEX manifestine kaydedilir. Manifest, linkerconfig tarafından işlenir. Böylece, harici yerel bağımlılıklar çalışma zamanında kullanılabilir.

Aşağıdaki snippet'te APEX hem ikili dosyayı (my_service) hem de kararlı olmayan bağımlılıkları (*.so dosyaları) içerir.

apex {
  ..
  vendor: true,
  binaries: ["my_service"],
  ..
}

Aşağıdaki snippet'te APEX, paylaşılan kitaplığı my_standalone_libve yukarıda açıklandığı gibi kararlı olmayan tüm bağımlılıklarını içerir.

apex {
  ..
  vendor: true,
  native_shared_libs: ["my_standalone_lib"],
  ..
}

APEX'i küçültme

APEX, kararlı olmayan bağımlılıkları paketlediği için daha büyük olabilir. Statik bağlantı kullanmanızı öneririz. libc++.so ve libbase.so gibi yaygın kitaplıklar, HAL ikili dosyalarına statik olarak bağlanabilir. Kararlı bir arayüz sağlamak için bağımlılık oluşturmak da başka bir seçenek olabilir. Bağımlılık APEX'e dahil edilmez.

HAL uygulamaları

HAL uygulamasını tanımlamak için aşağıdaki örneklere benzer şekilde bir tedarikçi APEX'inde ilgili ikili dosyaları ve kitaplıkları sağlayın:

HAL uygulamasını tamamen kapsayabilmek için APEX, ilgili tüm VINTF parçalarını ve başlatma komut dosyalarını da belirtmelidir.

VINTF parçaları

VINTF parçaları, APEX'in etc/vintf bölümünde bulunduğunda tedarikçi APEX'inden sunulabilir.

VINTF parçalarını APEX'e yerleştirmek için prebuilts mülkünü kullanın.

apex {
  ..
  vendor: true,
  prebuilts: ["fragment.xml"],
  ..
}

prebuilt_etc {
  name: "fragment.xml",
  src: "fragment.xml",
  sub_dir: "vintf",
}

Sorgu API'leri

VINTF parçaları APEX'e eklendiğinde HAL arayüzlerinin ve APEX adlarının eşlemelerini almak için libbinder_ndk API'lerini kullanın.

  • AServiceManager_isUpdatableViaApex("com.android.foo.IFoo/default") : true HAL örneği APEX'te tanımlanmışsa.
  • AServiceManager_getUpdatableApexName("com.android.foo.IFoo/default", ...) : HAL örneğini tanımlayan APEX adını alır.
  • AServiceManager_openDeclaredPassthroughHal("mapper", "instance", ...) : Geçiş HAL'i açmak için bunu kullanın.

İlklendirme komut dosyaları

APEX'ler, başlatma komut dosyalarını iki şekilde içerebilir: (A) APEX yükü içinde önceden oluşturulmuş bir metin dosyası veya (B) /vendor/etc içinde normal bir başlatma komut dosyası. Aynı APEX için ikisini de ayarlayabilirsiniz.

APEX'te ilklendirme komut dosyası:

prebuilt_etc {
  name: "myinit.rc",
  src: "myinit.rc"
}

apex {
  ..
  vendor: true,
  prebuilts: ["myinit.rc"],
  ..
}

Tedarikçi APEX'lerindeki ilklendirme komut dosyalarında service tanımları ve on <property or event> yönergeleri bulunabilir.

service tanımının aynı APEX'teki bir ikili dosyaya işaret ettiğinden emin olun. Örneğin, com.android.foo APEX, foo-service adlı bir hizmet tanımlayabilir.

on foo-service /apex/com.android.foo/bin/foo
  ...

on yönergelerini kullanırken dikkatli olun. APEX'lerdeki ilk script'ler, APEX'ler etkinleştirildikten sonra ayrıştırılıp yürütüldüğünden bazı etkinlikler veya mülkler kullanılamaz. İşlemleri mümkün olduğunca erken başlatmak için apex.all.ready=true öğesini kullanın. Bootstrap APEX'leri on init kullanabilir ancak on early-init kullanamaz.

Donanım Yazılımı

Örnek:

Aşağıdaki gibi prebuilt_firmware modül türüne sahip bir tedarikçi APEX'ine donanım yazılımını yerleştirin.

prebuilt_firmware {
  name: "my.bin",
  src: "path_to_prebuilt_firmware",
  vendor: true,
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.bin"],  // installed inside APEX as /etc/firmware/my.bin
  ..
}

prebuilt_firmware modülü, APEX'in <apex name>/etc/firmware dizinine yüklenir. ueventd, donanım yazılımı modüllerini bulmak için /apex/*/etc/firmware dizinlerini tarar.

APEX'in file_contexts, bu dosyaların çalışma zamanında ueventd tarafından erişilebilir olmasını sağlamak için tüm donanım yazılımı yükü girişlerini uygun şekilde etiketlemelidir. Genellikle vendor_file etiketi yeterlidir. Örnek:

(/.*)? u:object_r:vendor_file:s0

Çekirdek modülleri

Çekirdek modüllerini, aşağıdaki gibi önceden oluşturulmuş modüller olarak bir tedarikçi APEX'e yerleştirin.

prebuilt_etc {
  name: "my.ko",
  src: "my.ko",
  vendor: true,
  sub_dir: "modules"
}

apex {
  ..
  vendor: true,
  prebuilts: ["my.ko"],  // installed inside APEX as /etc/modules/my.ko
  ..
}

APEX'in file_contexts, tüm çekirdek modülü yükü girişlerini doğru şekilde etiketlemelidir. Örnek:

/etc/modules(/.*)? u:object_r:vendor_kernel_modules:s0

Çekirdek modülleri açıkça yüklenmiş olmalıdır. Tedarikçi firma bölümündeki aşağıdaki örnek ilk ayar komut dosyası, insmod üzerinden yüklemeyi gösterir:

my_init.rc:

on early-boot
  insmod /apex/myapex/etc/modules/my.ko
  ..

Çalışma zamanında kaynak yer paylaşımları

Örnek:

rros mülkünü kullanarak çalışma zamanında kaynak yer paylaşımlarını bir tedarikçi APEX'ine yerleştirin.

runtime_resource_overlay {
    name: "my_rro",
    soc_specific: true,
}


apex {
  ..
  vendor: true,
  rros: ["my_rro"],  // installed inside APEX as /overlay/my_rro.apk
  ..
}

Diğer yapılandırma dosyaları

Tedarikçi APEX'leri, genellikle tedarikçi bölümünde bulunan diğer çeşitli yapılandırma dosyalarını tedarikçi APEX'leri içinde önceden oluşturulmuş olarak destekler. Daha fazlası da eklenmektedir.

Örnekler:

Tedarikçi APEX'lerini önyükleme

keymint gibi bazı HAL hizmetleri, APEX'ler etkinleştirilmeden önce kullanılabilir olmalıdır. Bu HAL'ler genellikle init komut dosyasında hizmet tanımlarında early_hal değerini ayarlar. Başka bir örnek de genellikle post-fs-data etkinliğinden daha önce başlatılan animation sınıfıdır. Bu tür erken bir HAL hizmeti tedarikçi APEX'te paketlendiğinde, daha erken etkinleştirilebilmesi için APEX manifest dosyasında apex'i "vendorBootstrap": true yapın. APEX önyüklemelerinin yalnızca /data/apex yerine /vendor/apex gibi önceden oluşturulmuş konumlardan etkinleştirilebileceğini unutmayın.

Sistem özellikleri

Çerçeve, tedarikçi APEX'lerini desteklemek için okuduğu sistem özellikleri şunlardır:

  • input_device.config_file.apex=<apex name>: Ayarlandığında, giriş yapılandırma dosyaları (*.idc, *.kl ve *.kcm) APEX'in /etc/usr dizininde aranır.
  • ro.vulkan.apex=<apex name>: Ayarlandığında Vulkan sürücüsü APEX'ten yüklenir. Vulkan sürücüsü eski HAL'ler tarafından kullanıldığı için APEX'i Bootstrap APEX yapın ve bu bağlayıcı ad alanını görünür olarak yapılandırın.

setprop komutunu kullanarak init komut dosyalarında sistem özelliklerini ayarlayın.

Ek geliştirme özellikleri

APEX'i başlatma sırasında seçme

Örnek:

Geliştiriciler, aynı APEX adını ve anahtarını paylaşan tedarikçi APEX'lerinin birden fazla sürümünü yükleyebilir ve ardından kalıcı sysprops kullanarak her önyükleme sırasında hangi sürümün etkinleştirileceğini seçebilir. Bu, belirli geliştirici kullanım alanları için adb install kullanarak APEX'in yeni bir kopyasını yüklemekten daha basit olabilir.

Kullanım alanı örnekleri:

  • Kablosuz HAL tedarikçi APEX'in 3 sürümünü yükleyin: KG ekipleri, bir sürümü kullanarak manuel veya otomatik test çalıştırabilir, ardından başka bir sürüme yeniden başlayıp testleri yeniden çalıştırabilir ve nihai sonuçları karşılaştırabilir.
  • Kamera HAL tedarikçi APEX'in mevcut ve deneysel olmak üzere 2 sürümünü yükleyin: Dogfooders, ek bir dosya indirip yüklemeden deneysel sürümü kullanabilir. Böylece kolayca geri geçiş yapabilirler.

apexd, doğru APEX sürümünü etkinleştirmek için önyükleme sırasında belirli bir biçimi izleyen sysprops'leri arar.

Mülk anahtarı için beklenen biçimler şunlardır:

  • Bootconfig
    • BoardConfig.mk içinde varsayılan değeri ayarlamak için kullanılır.
    • androidboot.vendor.apex.<apex name>
  • Kalıcı sysprop
    • Zaten başlatılmış bir cihazda ayarlanan varsayılan değeri değiştirmek için kullanılır.
    • Varsa bootconfig değerini geçersiz kılar.
    • persist.vendor.apex.<apex name>

Özelliğin değeri, etkinleştirilmesi gereken APEX dosyasının adıdır.

// Default version.
apex {
  name: "com.oem.camera.hal.my_apex_default",
  vendor: true,
  ..
}

// Non-default version.
apex {
  name: "com.oem.camera.hal.my_apex_experimental",
  vendor: true,
  ..
}

Varsayılan sürüm, BoardConfig.mk içinde bootconfig kullanılarak da yapılandırılmalıdır:

# Example for APEX "com.oem.camera.hal" with the default above:
BOARD_BOOTCONFIG += \
    androidboot.vendor.apex.com.oem.camera.hal=com.oem.camera.hal.my_apex_default

Cihaz açıldıktan sonra kalıcı sysprop ayarını yaparak etkinleştirilen sürümü değiştirin:

$ adb root;
$ adb shell setprop \
    persist.vendor.apex.com.oem.camera.hal \
    com.oem.camera.hal.my_apex_experimental;
$ adb reboot;

Cihaz, önyükleme işleminin ardından bootconfig'in güncellenmesini destekliyorsa (fastboot oem komutları aracılığıyla gibi) çoklu yüklenen APEX için bootconfig özelliği değiştirildiğinde, önyüklemede etkinleştirilen sürüm de değişir.

Cuttlefish tabanlı sanal referans cihazlarda, bootconfig mülkünü doğrudan başlatma sırasında ayarlamak için --extra_bootconfig_args komutunu kullanabilirsiniz. Örnek:

launch_cvd --noresume \
  --extra_bootconfig_args "androidboot.vendor.apex.com.oem.camera.hal:=com.oem.camera.hal.my_apex_experimental";