HAL'ler için AIDL

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ında stability: "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:

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:

  1. 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
    
  2. 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
    
  3. 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. veya toString gibi ihtiyaç duyabileceğiniz özellikler için ek açıklama equals.
  4. 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.
  5. Ö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 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 ve ServiceSpecificException 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.