Android 11, Android'de HAL'ler için AIDL kullanma özelliğini sunar. Bu da, mümkün olan en hızlı şekilde uygulamaya başladı. AIDL kullanmak için geçiş HAL'leri Yalnızca mümkün olduğunda (yayın öncesi HAL'ler HIDL kullandığında, HIDL kullanılmalıdır).
Çerçeve bileşenleri gibi çerçeve bileşenleri arasında iletişim kurmak için AIDL kullanan HAL'ler
system.img
ve vendor.img
gibi donanım bileşenleri
Kararlı AIDL. Ancak, bir bölüm içinde iletişim kurmak için (örneğin,
HAL'yi kullanmayı tercih ederseniz kullanım IPC mekanizmasıyla ilgili bir kısıtlama yoktur.
Motivasyon
AIDL, HIDL'den daha uzun süredir mevcut ve Android çerçeve bileşenleri veya uygulamalar arasında fark yaratıyor. AIDL artık kararlılık desteğinde, tek bir IPC çalışma zamanıyla tüm yığını uygulamak mümkündür. AIDL ayrıca HIDL'den daha iyi bir sürüm oluşturma sistemine sahip.
- Tek bir IPC dili kullanmak, öğrenmek, hata ayıklamak ve yardımcı olur.
- AIDL, arayüz sahipleri için yerinde sürüm oluşturmayı destekler:
- Sahipler, arayüzlerin sonuna yöntemler veya parseller için alanlar ekleyebilir. Bu da yıllar içinde sürüm kodunun daha kolay olması anlamına gelir. yıllık maliyet daha küçüktür (türler yerinde değiştirilebilir ve (her arayüz sürümü için ek kitaplıklar gerekir).
- Uzantı arayüzleri tür yerine çalışma zamanında eklenebilir Bu nedenle, aşağı akış uzantılarının yeni Google Hesaplarına belirlemektir.
- Mevcut bir AIDL arayüzü, sahibi seçtiğinde doğrudan kullanılabilir sabitleyin. Önceden, arayüzün bütün bir kopyasının bir örneğidir.
AIDL çalışma zamanına göre geliştirme yapın
AIDL'nin üç farklı arka ucu vardır: Java, NDK ve CPP. Kararlı AIDL'yi kullanmak için:
her zaman system/lib*/libbinder.so
konumunda libbinder'ın sistem kopyasını kullanın ve konuşun
/dev/binder
tarihinde. Tedarikçi firma görüntüsündeki kod için bu, libbinder
anlamına gelir.
(VNDK'dan) kullanılamaz: Bu kitaplıkta kararsız bir C++ API'si ve
istikrarsız dahili unsurlar. Bunun yerine, yerel tedarikçi firma kodu,
AIDL, libbinder_ndk
(libbinder.so
sistemi tarafından desteklenir) için bağlantı
ve aidl_interface
giriş tarafından oluşturulan NDK kitaplıklarına bağlanmalıdır. Örneğin,
tam modül adlarını öğrenmek için bkz.
modül adlandırma kurallarına uygun olduğundan emin olun.
AIDL HAL arayüzü yazma
AIDL arayüzünün sistem ve tedarikçi arasında kullanılması için arayüzün iki değişiklik var:
- Her tür tanımı
@VintfStability
ile açıklanmalıdır. aidl_interface
beyanındastability: "vintf",
bulunmalıdır.
Bu değişiklikleri yalnızca arayüzün sahibi yapabilir.
Bu değişiklikleri yaptığınızda, arayüz,
VINTF manifest'ini inceleyin. Bunu (ve ilgili
(yayınlanan arayüzlerin dondurulduğunu doğrulama gibi)
VTS testi vts_treble_vintf_vendor_test
. @VintfStability
kullanabilirsiniz
bu şartlardan birini kullanmadan,
NDK arka ucunda AIBinder_forceDowngradeToLocalStability
,
android::Stability::forceDowngradeToLocalStability
, C++ arka ucunda,
veya Java arka ucunda android.os.Binder#forceDowngradeToSystemStability
bir bağlayıcı nesne üzerinde çalışır. Bir hizmetin sürümünü eski sürüme geçirme
Tüm uygulamalar bir sistemde çalıştırıldığı için Java'da tedarikçi kararlılığına yönelik destek desteklenmez
bağlam.
Ayrıca, maksimum kod taşınabilirliği sağlamak ve Gereksiz ek kitaplıklar olarak kullanmak istemiyorsanız, PBM arka ucunu devre dışı bırakın.
Aşağıdaki kod örneğinde backends
kullanımının doğru olduğuna dikkat edin, çünkü
üç arka uçtur (Java, NDK ve PBM). Aşağıdaki kod,
özellikle PBM arka ucunu devre dışı bırakın.
aidl_interface: {
...
backends: {
cpp: {
enabled: false,
},
},
}
AIDL HAL arayüzlerini bulma
HAL'ler için AOSP Kararlı AIDL arayüzleri
HIDL arayüzleri aidl
klasördedir.
- donanım/arayüzler
- çerçeveler/donanım/arayüzler
- sistem/donanım/arayüzler
Uzantı arayüzlerini diğer hardware/interfaces
vendor
veya hardware
alt dizinleri için geçerlidir.
Uzantı arayüzleri
Android'in her sürümde bir dizi resmi AOSP arayüzü vardır. Android iş ortakları bu arayüzlere işlev eklemek istediklerinden, bu arayüzlerin Çünkü bu, Android çalışma zamanının en az AOSP Android çalışma zamanıyla uyumlu değil. GMS cihazları için bu arayüzler aynı zamanda GSI görüntüsünün çalışmaya devam etmesini sağlar.
Uzantılar iki farklı şekilde kaydedilebilir:
- için ekteki uzantılara bakın.
- dünya genelinde ve VINTF'de kayıtlı olmalıdır.
Ancak tedarikçiye özgü (yani tedarikçinin yukarı akış AOSP) bileşenleri arayüzü kullanır, birleştirme işlemi yapılamaz. çatışmaya neden olabilir. Ancak yukarı akış AOSP bileşenlerinde yapılan aşağı akış değişiklikleri, birleştirme çakışmaları oluşabilir ve aşağıdaki stratejiler önerilir:
- arayüz eklemelerinin bir sonraki sürümde AOSP'ye yayınlanması
- birleştirme çakışmaları olmadan daha fazla esneklik sağlayan arayüz eklemeleri sonraki sürümde yayınlanabilecek
Uzantı paketleri: ParcelableHolder
ParcelableHolder
, başka bir Parcelable
içerebilen bir Parcelable
.
ParcelableHolder
öğesinin ana kullanım alanı, Parcelable
uzantısını genişletilebilir hale getirmektir.
Örneğin, cihaz uygulayıcılarının
AOSP tarafından tanımlanan Parcelable
, AospDefinedParcelable
(katma değerini dahil etmek için)
özellikleri.
Daha önce ParcelableHolder
olmadan, cihazı uygulayıcılar değişiklik yapamıyordu
AOSP tanımlı kararlı bir AIDL arayüzü eklemek, daha fazla ekleme yapmak hata olacaktır
alanlar:
parcelable AospDefinedParcelable {
int a;
String b;
String x; // ERROR: added by a device implementer
int[] y; // added by a device implementer
}
Önceki kodda gösterildiği gibi bu uygulama, ayrıştırıcısı tarafından eklenen bir sürümle ilgili bir çakışma olabilir. Android'in sonraki sürümlerinde revizyondan geçmiş olacak.
Bir ayrıştırılabilir öğenin sahibi, ParcelableHolder
kullanarak bir uzantı tanımlayabilir
bir Parcelable
konumu.
parcelable AospDefinedParcelable {
int a;
String b;
ParcelableHolder extension;
}
Daha sonra, cihaz uygulayıcıları kendi Parcelable
tanımlayıcılarını
uzantısına sahip olur.
parcelable OemDefinedParcelable {
String x;
int[] y;
}
Son olarak, yeni Parcelable
, aşağıdaki gibi orijinal Parcelable
öğesine eklenebilir:
ParcelableHolder
alanına girin.
// Java
AospDefinedParcelable ap = ...;
OemDefinedParcelable op = new OemDefinedParcelable();
op.x = ...;
op.y = ...;
ap.extension.setParcelable(op);
...
OemDefinedParcelable op = ap.extension.getParcelable(OemDefinedParcelable.class);
// C++
AospDefinedParcelable ap;
OemDefinedParcelable op;
std::shared_ptr<OemDefinedParcelable> op_ptr = make_shared<OemDefinedParcelable>();
ap.extension.setParcelable(op);
ap.extension.setParcelable(op_ptr);
...
std::shared_ptr<OemDefinedParcelable> op_ptr;
ap.extension.getParcelable(&op_ptr);
// NDK
AospDefinedParcelable ap;
OemDefinedParcelable op;
ap.extension.setParcelable(op);
...
std::optional<OemDefinedParcelable> op;
ap.extension.getParcelable(&op);
// Rust
let mut ap = AospDefinedParcelable { .. };
let op = Rc::new(OemDefinedParcelable { .. });
ap.extension.set_parcelable(Rc::clone(&op));
...
let op = ap.extension.get_parcelable::<OemDefinedParcelable>();
AIDL HAL sunucusu örneği adları
Geleneksel olarak AIDL HAL hizmetleri şu biçimde bir örnek adına sahiptir:
$package.$type/$instance
Örneğin, titreşim HAL'sinin bir örneği:
android.hardware.vibrator.IVibrator/default
olarak kayıtlı.
AIDL HAL sunucusu yazma
@VintfStability
AIDL sunucuları,
aşağıdaki gibi bir örnek oluşturabilirsiniz:
<hal format="aidl">
<name>android.hardware.vibrator</name>
<version>1</version>
<fqname>IVibrator/default</fqname>
</hal>
Aksi takdirde, AIDL hizmetini normal şekilde kaydetmeleri gerekir. VTS'yi çalıştırırken beyan edilen tüm AIDL HAL'lerin kullanılabilir olması beklenir.
AIDL istemcisi yaz
AIDL istemcileri, uyumluluk matrisinde kendilerini beyan etmelidir. Örneğin, aşağıdaki gibidir:
<hal format="aidl" optional="true">
<name>android.hardware.vibrator</name>
<version>1-2</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
Mevcut bir HAL'yi HIDL'den AIDL'ye dönüştürme
HIDL arayüzünü AIDL'ye dönüştürmek için hidl2aidl
aracını kullanın.
hidl2aidl
özellikleri:
- Belirtilen paket için
.hal
dosyalarına dayalı.aidl
dosyaları oluşturun - Yeni oluşturulan AIDL paketi için tüm arka uçlarla derleme kuralları oluşturun etkin
- Çeviri için Java, CPP ve NDK arka uçlarında çeviri yöntemleri oluşturma ve HIDL türlerinden AIDL türlerine
- Gerekli bağımlılıklara sahip çeviri kitaplıkları için derleme kuralları oluşturma
- HIDL ve AIDL numaralandırıcılarının PBM ve NDK arka uçlarında aynı değerlere
Bir .hal dosyası paketini .aidl dosyalarına dönüştürmek için aşağıdaki adımları uygulayın:
system/tools/hidl/hidl2aidl
adresindeki aracı oluşturun.Bu aracı en yeni kaynaktan oluşturmak, sahip olacaksınız. Eski arayüzleri dönüştürmek için en son sürümü kullanabilirsiniz önceki sürümlerden dallar.
m hidl2aidl
Aracı bir çıkış diziniyle ve ardından çalıştırılacak paketle yürütün dönüştürüldü.
İsteğe bağlı olarak, yeni lisans dosyasının içeriğini eklemek için
-l
bağımsız değişkenini kullanın eklenir. Doğru lisansı ve tarihi kullandığınızdan emin olun.hidl2aidl -o <output directory> -l <file with license> <package>
Örnek:
hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
Oluşturulan dosyaları okuyun ve dönüşümle ilgili sorunları giderin.
conversion.log
, öncelikle düzeltilmesi gereken sorunları içeriyor.- Oluşturulan
.aidl
dosyada uyarı ve öneriler olabilir. gerek yok. Bu yorumlar//
ile başlıyor. - Paketi temizleme ve pakette iyileştirmeler yapma fırsatından yararlanabilirsiniz.
@JavaDerive
bağlantısını kontrol edin. veyatoString
gibi ihtiyaç duyabileceğiniz özellikler için ek açıklamaequals
.
Yalnızca ihtiyacınız olan hedefleri oluşturun.
- Kullanılmayan arka uçları devre dışı bırakın. PBM yerine NDK arka ucunu tercih et çalışma zamanını seçme bölümüne bakın.
- Çeviri kitaplıklarını veya kullanılmayacak olan kodları kaldırın.
Önemli AIDL/HIDL farkları konusuna bakın.
- AIDL'nin yerleşik
Status
ve istisnalarının kullanılması genellikle diğer bir arayüze özgü durum türüne olan ihtiyacı ortadan kaldırın. - Yöntemlerdeki AIDL arayüzü bağımsız değişkenleri varsayılan olarak
@nullable
biçiminde değildir, HIDL'deydi.
- AIDL'nin yerleşik
AIDL HAL'lere ilişkin SEPolitikası
Tedarikçi firma kodu tarafından görülebilen bir AIDL hizmet türü,
hal_service_type
özelliği için de kullanılmaktadır. Aksi takdirde sepolicy yapılandırması aynı olur.
(HAL'ler için özel özellikler vardır.) Burası
HAL hizmeti bağlamının örnek bir tanımıdır:
type hal_foo_service, service_manager_type, hal_service_type;
Platform tarafından tanımlanan çoğu hizmet için doğru
türü zaten eklenmiş (örneğin, android.hardware.foo.IFoo/default
zaten hal_foo_service
olarak işaretli). Ancak bir çerçeve istemcisi
varsa, buraya ek örnek adları eklenmelidir
cihaza özel service_contexts
dosyaları.
android.hardware.foo.IFoo/custom_instance u:object_r:hal_foo_service:s0
Yeni bir HAL türü oluşturduğumuzda HAL özellikleri eklenmelidir. Belirli bir HAL
özelliği birden fazla hizmet türüyle ilişkilendirilebilir (her biri
az önce konuştuğumuz gibi birden fazla örneği olur). foo
HAL için
hal_attribute(foo)
. Bu makro, hal_foo_client
ve
hal_foo_server
. Belirli bir alan için hal_client_domain
ve
hal_server_domain
makroları, bir alanı belirli bir HAL özelliğiyle ilişkilendirir. Örneğin,
Örneğin, sistem sunucusunun bu HAL'nin istemcisi olması,
hal_client_domain(system_server, hal_foo)
Bir HAL sunucusu da benzer şekilde
hal_server_domain(my_hal_domain, hal_foo)
Genellikle, belirli bir HAL
özelliğini kullanarak, referans olması için hal_foo_default
veya
kullanabilirsiniz. Ancak bazı cihazlar bu alan adlarını kendi sunucuları için kullanır.
Birden çok sunucu için alan adlarını ayırt etmek yalnızca
aynı arayüzü sunan ve farklı bir izne ihtiyaç duyan birden çok sunucu
göz önünde bulundurun. Bu makroların tümünde hal_foo
, aslında
sepolicy nesnesi. Bunun yerine, bu jeton bu makrolar tarafından
istemci sunucu çiftiyle ilişkilendirilmiş özellik grubu.
Ancak, hal_foo_service
ve hal_foo
verilerini şu ana kadar ilişkilendirmedik
(hal_attribute(foo)
alanındaki özellik çifti). Bir HAL özelliği ilişkilendirilmiş
hal_attribute_service
makrosu kullanarak AIDL HAL hizmetleriyle (HIDL HAL'ler,
hal_attribute_hwservice
makrosu). Örneğin,
hal_attribute_service(hal_foo, hal_foo_service)
Bunun anlamı,
hal_foo_client
işlem HAL'yi ele alabilir ve hal_foo_server
HAL kaydedebilir. Bu kayıt kurallarının uygulanması
bağlam yöneticisi (servicemanager
) tarafından yapılır. Dikkat edin, hizmet adları
her zaman HAL özelliklerine karşılık gelmez. Örneğin, bir açılış
hal_attribute_service(hal_foo, hal_foo2_service)
Ancak genellikle
hizmetlerin her zaman birlikte kullanılması gerektiği anlamına gelir.
tüm hizmetlerimiz için hal_foo2_service
ve hal_foo_service
kullanıyor
bağlamlar. Birden fazla hal_attribute_service
ayarlayan HAL'lerin çoğunun nedeni:
orijinal HAL özelliği adı yeterince genel değil ve değiştirilemez.
Hepsini bir araya getirdiğimizde, bir HAL örneği şu şekilde olacaktır:
public/attributes:
// define hal_foo, hal_foo_client, hal_foo_server
hal_attribute(foo)
public/service.te
// define hal_foo_service
type hal_foo_service, hal_service_type, protected_service, service_manager_type
public/hal_foo.te:
// allow binder connection from client to server
binder_call(hal_foo_client, hal_foo_server)
// allow client to find the service, allow server to register the service
hal_attribute_service(hal_foo, hal_foo_service)
// allow binder communication from server to service_manager
binder_use(hal_foo_server)
private/service_contexts:
// bind an AIDL service name to the selinux type
android.hardware.foo.IFooXxxx/default u:object_r:hal_foo_service:s0
private/<some_domain>.te:
// let this domain use the hal service
binder_use(some_domain)
hal_client_domain(some_domain, hal_foo)
vendor/<some_hal_server_domain>.te
// let this domain serve the hal service
hal_server_domain(some_hal_server_domain, hal_foo)
Ekli uzantı arayüzleri
Bir uzantı, ister üst düzey ister başka bir bağlayıcı arayüzüne eklenebilir veya bir alt arayüzdür. Bir uzantı alırken, uzantının türünün şu şekilde olduğunu onaylamanız gerekir: bekleniyor. Uzantılar, yalnızca bağlayıcı sunan işlemden ayarlanabilir.
Ekli uzantılar, işlevlerine sahip değildir. Tamamen yeni bir işlev gerektiğinde bu mekanizmanın kullanılması gerekmez ve bir uzantı arayüzü kaydını tutmalısınız. Ekli uzantı arayüzleri Bunlar alt arayüzlere bağlı olduklarında daha mantıklıdırlar. Çünkü hiyerarşiler derin veya birden çok örnekli olabilir. Yansıtma için global uzantı kullanma başka bir hizmetin bağlayıcı arayüzü hiyerarşisi, muhasebe kaydı, doğrudan eklenen uzantılara eşdeğer işlevler sunmaktır.
Bağlayıcıda bir uzantı ayarlamak için aşağıdaki API'leri kullanın:
- NDK arka ucunda:
AIBinder_setExtension
- Java arka ucunda:
android.os.Binder.setExtension
- PBM arka ucunda:
android::Binder::setExtension
- Rust arka ucunda:
binder::Binder::set_extension
Bir bağlayıcıda uzantı almak için aşağıdaki API'leri kullanın:
- NDK arka ucunda:
AIBinder_getExtension
- Java arka ucunda:
android.os.IBinder.getExtension
- PBM arka ucunda:
android::IBinder::getExtension
- Rust arka ucunda:
binder::Binder::get_extension
Bu API'ler hakkında daha fazla bilgiyi
getExtension
işlevini kullanın. Örnek olarak
uzantıları şurada bulabilirsiniz:
donanım/arayüzler/testler/uzantı/titreşim.
Önemli AIDL ve HIDL farklılıkları
AIDL HAL'leri veya AIDL HAL arayüzlerini kullanırken aradaki farka dikkat edin karşılaştırabilirsiniz.
- AIDL dilinin söz dizimi Java'ya daha yakındır. HIDL söz dizimi C++ ile benzer.
- Tüm AIDL arayüzlerinde yerleşik hata durumları bulunur. Her bir ürün için
arayüz dosyalarında sabit durum int'leri oluşturun ve
PBM/NDK arka uçlarında
EX_SERVICE_SPECIFIC
veServiceSpecificException
arka ucunda test etmeyi unutmayın. Bkz. Hata Kullanım. - AIDL, bağlayıcı nesneleri gönderildiğinde iş parçacığı havuzlarını otomatik olarak başlatmaz. Bunların manuel olarak başlatılması gerekir (bkz. ileti dizisi yönetimi).
- AIDL, kontrol edilmeyen aktarım hatalarında iptal etmez (HIDL
Return
şu tarihte iptal eder: kontrol edilmemiş hatalardır). - AIDL dosya başına yalnızca bir tür tanımlayabilir.
- AIDL bağımsız değişkenleri, çıkışa ek olarak giriş/çıkış/inout olarak da belirtilebilir parametresini ("eşzamanlı geri çağırmalar" yoktur).
- AIDL, temel tür olarak herkese açık kullanıcı adı yerine fd kullanır.
- HIDL, uyumsuz değişiklikler için ana sürümleri,
uyumlu değişiklikler olduğundan emin olun. AIDL'de geriye dönük uyumlu değişiklikler uygulanır.
AIDL'de ana sürümlerle ilgili açık bir kavram yoktur; bunun yerine bu
paket adlarına dahil edilir. Örneğin, AIDL paket adını kullanabilir
bluetooth2
- AIDL varsayılan olarak gerçek zamanlı önceliği devralmaz.
setInheritRt
işlevi, gerçek zamanlı öncelik devralmayı etkinleştirmek için bağlayıcı başına kullanılmalıdır.