Tedarikçi APEX

Daha düşük seviyeli 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 oluşturulmasına 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 resimlerinin modülerleştirilmesi

APEX'ler, satıcı resimlerindeki özellik uygulamalarının doğal olarak paketlenmesini ve modülerleştirilmesini kolaylaştırır.

Tedarikçi resimleri, bağımsız olarak oluşturulmuş tedarikçi APEX'lerinin bir kombinasyonu olarak oluşturulduğunda cihaz üreticileri, cihazlarında istedikleri belirli tedarikçi uygulamalarını kolayca seçebilir. Üreticiler, sağlanan APEX'lerden hiçbiri ihtiyaçlarına uygun değilse veya yepyeni bir özel donanımları varsa yeni bir satıcı APEX'i bile oluşturabilir.

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

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

Geliştirici yinelemesi

Tedarikçi APEX'leri, geliştiricilerin tedarikçi modüllerini geliştirirken daha hızlı yineleme yapmasına yardımcı olur. Bunu, WiFi HAL gibi tüm özellik uygulamalarını bir tedarikçi APEX'i içinde paketleyerek yapar. Böylece geliştiriciler, satıcı APEX'ini test değişikliklerine göre ayrı ayrı oluşturup gönderebilir ve satıcı imajının tamamını yeniden oluşturmak zorunda kalmaz.

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

Bir özellik alanının APEX'e doğal olarak paketlenmesi, bu özellik alanıyla ilgili değişikliklerin oluşturulması, gönderilmesi ve test edilmesi sürecini de basitleştirir. Örneğin, bir APEX'in yeniden yüklenmesi, APEX'in içerdiği tüm paketlenmiş kitaplık veya yapılandırma dosyalarını otomatik olarak günceller.

Bir özellik alanını APEX'e dahil etmek, kötü cihaz davranışı gözlemlendiğinde hata ayıklamayı veya geri döndürmeyi de kolaylaştırır. Örneğin, yeni bir derlemede telefon özelliği düzgün çalışmıyorsa geliştiriciler, cihaza daha eski bir telefon özelliği uygulaması APEX'i yükleyip (tam derleme flaşlamaya gerek kalmadan) iyi davranışın geri gelip gelmediğ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 koşulları, 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ını inceleyin.

Android.bp içinde vendor: true özelliğinin ayarlanması, APEX modülünü satıcı APEX'i yapar.

apex {
  ..
  vendor: true,
  ..
}

İkili dosyalar ve paylaşılan kitaplıklar

APEX'ler, kararlı arayüzlere sahip olmadıkları 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, cc_library ile stubs ve LLNDK kitaplıklarını içerir. Bu bağımlılıklar paketlemeye dahil edilmez ve bağımlılıklar 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 ikiliyi (my_service) hem de kararlı olmayan bağımlılıklarını (*.so dosyaları) içerir.

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

Aşağıdaki snippet'te APEX, paylaşılan kitaplığı ve kararlı olmayan bağımlılıklarını (yukarıda açıklandığı gibi) içerir.my_standalone_lib

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 ikililerine 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ı

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

HAL uygulamasını tam olarak kapsamak için APEX, ilgili VINTF parçalarını ve init komut dosyalarını da belirtmelidir.

VINTF parçaları

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

VINTF parçalarını APEX'e yerleştirmek için prebuilts özelliğini kullanın.

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

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

Query 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", ...) : Bu komut, doğrudan geçişli bir HAL'ı açmak için kullanılır.

Init komut dosyaları

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

APEX'teki başlatma komut dosyası:

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

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

Tedarikçi APEX'lerindeki başlatma komut dosyaları service tanımlarına ve on <property or event> yönergelerine sahip olabilir.

Bir service tanımının aynı APEX'teki bir ikiliye 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 başlatma komut dosyaları, APEX'ler etkinleştirildikten sonra ayrıştırılıp yürütüldüğünden bazı etkinlikler veya özellikler kullanılamaz. İşlemleri mümkün olduğunca erken tetiklemek için apex.all.ready=true kullanın. Bootstrap APEX'leri on init kullanabilir ancak on early-init kullanamaz.

Donanım yazılımı

Örnek:

Donanım yazılımını, aşağıdaki gibi prebuilt_firmware modül türüyle bir tedarikçi APEX'ine 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
  ..
}

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

on early-init

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 düzgün şekilde etiketlemelidir. Genellikle vendor_file etiketi yeterlidir. Örneğin:

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

Çekirdek modülleri

Çekirdek modüllerini, aşağıdaki şekilde önceden oluşturulmuş modüller olarak bir satıcı APEX'ine 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 düzgün şekilde etiketlemelidir. Örneğin:

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

Çekirdek modülleri açıkça yüklenmelidir. Aşağıdaki örnekte, satıcı bölümündeki bir başlatma komut dosyası, insmod üzerinden yüklemeyi göstermektedir:

my_init.rc:

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

Çalışma zamanında kaynak eşlemeleri

Örnek:

rros özelliğini kullanarak bir satıcı APEX'ine çalışma zamanı kaynak yer paylaşımları 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 çeşitli yapılandırma dosyalarını tedarikçi APEX'lerinde önceden oluşturulmuş olarak destekler ve daha fazlası eklenmektedir.

Örnekler:

Bootstrap Vendor APEXes

keymint gibi bazı HAL hizmetleri, APEX'ler etkinleştirilmeden önce kullanılabilir olmalıdır. Bu HAL'ler genellikle başlatma komut dosyasındaki hizmet tanımlarında early_hal değerini ayarlar. Başka bir örnek de post-fs-data etkinliğinden genellikle daha önce başlayan animation sınıfıdır. Bu tür erken HAL hizmetleri, satıcı APEX'inde paketlendiğinde, APEX Manifest'inde "vendorBootstrap": true olarak işaretleyin. Böylece daha erken etkinleştirilebilir. Başlangıç APEX'lerinin yalnızca /vendor/apex gibi önceden oluşturulmuş konumdan etkinleştirilebileceğini, /data/apex konumundan etkinleştirilemeyeceğini unutmayın.

Sistem özellikleri

Çerçeve, satıcı APEX'lerini desteklemek için aşağıdaki sistem özelliklerini okur:

  • 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ü erken HAL'ler tarafından kullanıldığından APEX'i Bootstrap APEX olarak ayarlayın ve bağlayıcı ad alanını görünür olacak şekilde yapılandırın.

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

Ek özellikler

Başlatma sırasında APEX seçimi

Örnek:

Tedarikçi APEX'leri, başlatma sırasında isteğe bağlı olarak etkinleştirilebilir. Sistem özelliğini kullanarak bir dosya adı belirtirseniz ro.vendor.apex.<apex name>, yalnızca dosya adıyla eşleşen APEX, belirli <apex name> için etkinleştirilir. Bu sistem özelliği none olarak ayarlanırsa <apex name> içeren APEX yoksayılır (etkinleştirilmez). Bu özelliği, aynı ada sahip bir APEX'in birden fazla kopyasını yüklemek için kullanabilirsiniz. Aynı APEX'in birden fazla sürümü varsa aynı anahtarı paylaşmalıdırlar.

Kullanım alanı örnekleri:

  • Kablosuz HAL sağlayıcı APEX'in 3 sürümünü yükleyin: KG ekipleri, bir sürümü kullanarak manuel veya otomatik testler çalıştırabilir, ardından başka bir sürümde yeniden başlatıp testleri tekrar çalıştırabilir ve son olarak sonuçları karşılaştırabilir.
  • Kamera HAL satıcısı APEX'in 2 sürümünü (mevcut ve deneysel) yükleyin: Dogfood kullanıcıları, ek bir dosya indirmeden ve yüklemeden deneysel sürümü kullanabilir. Böylece kolayca geri dönebilirler.

Başlatma sırasında apexd, doğru APEX sürümünü etkinleştirmek için belirli bir biçime sahip sysprop'ları arar.

Özellik anahtarı için beklenen biçimler şunlardır:

  • Bootconfig
    • Varsayılan değeri BoardConfig.mk cinsinden 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.
    • Mevcutsa bootconfig değerini geçersiz kılar.
    • persist.vendor.apex.<apex name>

Özelliğin değeri, etkinleştirilmesi gereken APEX'in dosya adı veya APEX'i devre dışı bırakmak için none olmalı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 de BoardConfig.mk içinde bootconfig kullanılarak 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 başlatıldıktan sonra, etkinleştirilen sürümü kalıcı sysprop'u ayarlayarak 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, yanıp sönme işleminden sonra bootconfig'in güncellenmesini destekliyorsa (ör. fastboot oem komutları aracılığıyla) çoklu yüklenmiş APEX'in bootconfig özelliğinin değiştirilmesi, başlatma sırasında etkinleştirilen sürümü de değiştirir.

Cuttlefish'e dayalı sanal referans cihazlarda, başlatma sırasında bootconfig özelliğini doğrudan ayarlamak için --extra_bootconfig_args komutunu kullanabilirsiniz. Örneğin:

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