AIDL Arka Uçları

Koleksiyonlar ile düzeninizi koruyun İçeriği tercihlerinize göre kaydedin ve kategorilere ayırın.

Bir AIDL arka ucu, saplama kodu üretimi için bir hedeftir. AIDL dosyalarını kullanırken, bunları her zaman belirli bir çalışma zamanı ile belirli bir dilde kullanırsınız. Bağlama bağlı olarak, farklı AIDL arka uçları kullanmalısınız.

AIDL aşağıdaki arka uçlara sahiptir:

arka uç Dil API yüzeyi Yapı sistemleri
java java SDK/SystemApi (kararlı*) herşey
NDK C++ libbinder_ndk (sabit*) aidl_interface
CPP C++ libbinder (kararsız) herşey
Pas Pas libbinder_rs (kararsız) aidl_interface
  • Bu API yüzeyleri kararlıdır, ancak hizmet yönetimi için olanlar gibi birçok API dahili platform kullanımı için ayrılmıştır ve uygulamalar tarafından kullanılamaz. AIDL'nin uygulamalarda nasıl kullanılacağı hakkında daha fazla bilgi için geliştirici belgelerine bakın.
  • Rust arka ucu Android 12'de tanıtıldı; NDK arka ucu, Android 10'dan itibaren kullanıma sunulmuştur.
  • Rust kasası, libbinder_ndk üzerine kuruludur. APEX'ler, ciltleme kasasını sistem tarafındaki diğer herkesle aynı şekilde kullanır. Rust kısmı bir APEX'e paketlenir ve içinde gönderilir. Sistem bölümündeki libbinder_ndk.so bağlıdır.

Yapı sistemleri

Arka uca bağlı olarak, AIDL'yi saplama kodunda derlemenin iki yolu vardır. Derleme sistemleri hakkında daha fazla ayrıntı için Soong Modülü Referansına bakın.

Çekirdek yapı sistemi

Herhangi bir cc_ veya java_ Android.bp modülünde (veya bunların Android.mk eşdeğerlerinde), .aidl dosyaları kaynak dosyalar olarak belirtilebilir. Bu durumda AIDL'nin Java/CPP arka uçları kullanılır (NDK arka ucu değil) ve karşılık gelen AIDL dosyalarını kullanacak sınıflar otomatik olarak modüle eklenir. Derleme sistemine söz konusu modüldeki AIDL dosyalarının kök yolunu söyleyen local_include_dirs gibi seçenekler, bu modüllerde bir aidl: grubu altında belirtilebilir. Rust arka ucunun yalnızca Rust ile kullanım için olduğunu unutmayın. rust_ modülleri, AIDL dosyalarının kaynak dosyalar olarak belirtilmemesi nedeniyle farklı şekilde ele alınır. Bunun yerine aidl_interface modülü, <aidl_interface name>-rust adlı ve ona karşı bağlanabilen bir rustlib üretir. Daha fazla ayrıntı için Rust AIDL örneğine bakın.

aidl_interface

Kararlı AIDL'ye bakın. Bu yapı sistemiyle kullanılan türler yapılandırılmalıdır; yani doğrudan AIDL'de ifade edilir. Bu, özel parsellenebilirlerin kullanılamayacağı anlamına gelir.

Türler

aidl derleyicisini türler için bir referans uygulaması olarak düşünebilirsiniz. Bir arabirim oluşturduğunuzda, ortaya çıkan arabirim dosyasını görmek için aidl --lang=<backend> ... . aidl_interface modülünü kullandığınızda, çıktıyı out/soong/.intermediates/<path to module>/ içinde görüntüleyebilirsiniz.

Java/AIDL Türü C++ Türü NDK Tipi Pas Tipi
mantıksal bool bool bool
bayt int8_t int8_t i8
karakter char16_t char16_t u16
int int32_t int32_t i32
uzun int64_t int64_t i64
batmadan yüzmek batmadan yüzmek batmadan yüzmek f32
çift çift çift f64
Sicim android::Dize16 std::dize Sicim
android.os.Parcelable android::Parcelable Yok Yok
Bağlayıcı android::IBinder ndk::SpAIBinder bağlayıcı::SpIBinder
T[] std::vektör<T> std::vektör<T> İçinde: &[T]
Çıkış: Vec<T>
bayt[] std::vector<uint8_t> std::vector<int8_t> 1 İçinde: &[u8]
Çıkan: Vec<u8>
Liste<T> std::vector<T> 2 std::vector<T> 3 İçinde: &[T] 4
Çıkış: Vec<T>
Dosya Tanımlayıcı android::base::unique_fd Yok bağlayıcı::parcel::ParcelFileDescriptor
ParselDosyaTanımlayıcı android::os::ParcelFileDescriptor ndk::ScopedFileDescriptor bağlayıcı::parcel::ParcelFileDescriptor
arayüz tipi (T) android::sp<T> std::shared_ptr<T> bağlayıcı::Güçlü
parsellenebilir tip (T) T T T
rakor tipi (T) 5 T T T
T[N] 6 std::array<T, N> std::array<T, N> [T; N]

1. Android 12 veya üzerinde, bayt dizileri uyumluluk nedenleriyle int8_t yerine uint8_t kullanır.

2. C++ arka ucu List<T> destekler; burada T , String , IBinder , ParcelFileDescriptor veya parsellenebilirdir. Android 13 veya sonraki sürümlerde T , diziler dışında herhangi bir ilkel olmayan tür olabilir (arayüz türleri dahil). AOSP, tüm arka uçlarda çalıştıkları için T[] gibi dizi türlerini kullanmanızı önerir.

3. NDK arka ucu, T'nin String , ParcelFileDescriptor veya parsellenebilir değerlerden biri olduğu List<T> T destekler. Android 13 veya sonraki sürümlerde T , diziler dışında herhangi bir ilkel olmayan tür olabilir.

4. Türler, giriş (argüman) veya çıkış (döndürülen değer) olmalarına bağlı olarak Rust kodu için farklı şekilde iletilir.

5. Birleşim türleri, Android 12 ve sonraki sürümlerde desteklenir.

6. Android 13 veya sonraki sürümlerde sabit boyutlu diziler desteklenir. Sabit boyutlu dizilerin birden çok boyutu olabilir (ör. int[3][4] ). Java arka ucunda, sabit boyutlu diziler, dizi türleri olarak temsil edilir.

Yönlülük (giriş/çıkış/giriş)

İşlevler için bağımsız değişken türlerini belirtirken, bunları in , out veya inout olarak belirtebilirsiniz. Bu, bir IPC çağrısı için hangi yön bilgisinin iletildiğini kontrol eder. in varsayılan yöndür ve arayandan aranana verilerin iletildiğini gösterir. out , verilerin aranandan arayana iletildiği anlamına gelir. inout , bunların her ikisinin birleşimidir. Ancak Android ekibi, inout bağımsız değişken belirticisini kullanmaktan kaçınmanızı önerir. inout sürümlü bir arabirim ve daha eski bir arananla kullanırsanız, yalnızca arayanda bulunan ek alanlar varsayılan değerlerine sıfırlanır. Rust ile ilgili olarak, normal bir giriş tipi &mut inout &mut Vec<T> alır ve bir liste giriş tipi &mut Vec<T> inout .

UTF8/UTF16

CPP arka ucu ile dizelerin utf-8 veya utf-16 olmasını seçebilirsiniz. Dizeleri otomatik olarak utf-8'e dönüştürmek için AIDL'de @utf8InCpp String olarak bildirin. NDK ve Rust arka uçları her zaman utf-8 dizelerini kullanır. utf8InCpp ek açıklaması hakkında daha fazla bilgi için bkz. AIDL'deki Ek Açıklamalar .

Nullabilite

Boş değerleri CPP ve NDK arka uçlarına göstermek için Java arka ucunda boş @nullable ile açıklama ekleyebilirsiniz. Rust arka ucunda bu @nullable türleri Option<T> olarak gösterilir. Yerel sunucular, boş değerleri varsayılan olarak reddeder. Bunun tek istisnası, NDK okumaları ve CPP/NDK yazmaları için her zaman boş olabilen interface ve IBinder türleridir. nullable yapılabilir açıklama hakkında daha fazla bilgi için bkz . AIDL'deki Ek Açıklamalar .

Özel Parseller

Çekirdek derleme sistemindeki C++ ve Java arka uçlarında, bir hedef arka uçta (C++ veya Java'da) manuel olarak uygulanan bir ayrıştırılabilir bildirebilirsiniz.

    package my.package;
    parcelable Foo;

veya C++ başlık bildirimi ile:

    package my.package;
    parcelable Foo cpp_header "my/package/Foo.h";

Daha sonra bu parsellenebiliri AIDL dosyalarında bir tür olarak kullanabilirsiniz, ancak AIDL tarafından oluşturulmayacaktır.

Rust, özel paketlenebilir öğeleri desteklemez.

Varsayılan değerler

Yapılandırılmış parsellenebilir öğeler, bu türlerdeki ilkel öğeler, String s ve diziler için alan başına varsayılan değerler bildirebilir.

    parcelable Foo {
      int numField = 42;
      String stringField = "string value";
      char charValue = 'a';
      ...
    }

Java arka ucunda, varsayılan değerler eksik olduğunda alanlar, ilkel türler için sıfır değerleri ve ilkel olmayan türler için null değer olarak başlatılır.

Diğer arka uçlarda, varsayılan değerler tanımlanmadığında alanlar, varsayılan olarak başlatılan değerlerle başlatılır. Örneğin, C++ arka ucunda, String alanları boş bir dize olarak başlatılır ve List<T> alanları boş bir vector<T> olarak başlatılır. @nullable alanlar, boş değerli alanlar olarak başlatılır.

Hata yönetimi

Android işletim sistemi, hizmetlerin hataları bildirirken kullanması için yerleşik hata türleri sağlar. Bunlar bağlayıcı tarafından kullanılır ve bir bağlayıcı arabirimi uygulayan herhangi bir hizmet tarafından kullanılabilir. Kullanımları AIDL tanımında iyi bir şekilde belgelenmiştir ve herhangi bir kullanıcı tanımlı durum veya dönüş türü gerektirmezler.

Hatalı çıktı parametreleri

Bir AIDL işlevi bir hata bildirdiğinde, işlev çıkış parametrelerini başlatamayabilir veya değiştiremeyebilir. Spesifik olarak, hata, işlemin kendisinin işlenmesi sırasında meydana gelmesinin aksine ayrıştırma sırasında meydana gelirse, çıktı parametreleri değiştirilebilir. Genel olarak, bir inout işlevinden hata alırken, tüm giriş ve out parametrelerinin yanı sıra (bazı arka uçlarda out parametresi gibi davranan) dönüş değerinin belirsiz durumda olduğu düşünülmelidir.

Hangi hata değerlerinin kullanılacağı

Yerleşik hata değerlerinin çoğu, herhangi bir AIDL arayüzünde kullanılabilir, ancak bazıları özel bir şekilde ele alınır. Örneğin, EX_UNSUPPORTED_OPERATION ve EX_ILLEGAL_ARGUMENT , hata koşulunu tanımladıklarında kullanılabilirler, ancak EX_TRANSACTION_FAILED , altta yatan altyapı tarafından özel olarak ele alındığı için kullanılmamalıdır. Bu yerleşik değerler hakkında daha fazla bilgi için arka uca özgü tanımları kontrol edin.

AIDL arabirimi yerleşik hata türlerinin kapsamadığı ek hata değerleri gerektiriyorsa, kullanıcı tarafından tanımlanan hizmete özgü bir hata değerinin eklenmesine izin veren özel hizmete özgü yerleşik hatayı kullanabilirler. . Bu hizmete özgü hatalar, genellikle AIDL arayüzünde bir const int veya int -backed enum olarak tanımlanır ve bağlayıcı tarafından ayrıştırılmaz.

Java'da hatalar, android.os.RemoteException gibi istisnalarla eşlenir. Hizmete özgü istisnalar için Java, kullanıcı tanımlı hatayla birlikte android.os.ServiceSpecificException kullanır.

Android'deki yerel kod istisnalar kullanmaz. CPP arka ucu android::binder::Status kullanır. NDK arka ucu ndk::ScopedAStatus kullanır. AIDL tarafından oluşturulan her yöntem, yöntemin durumunu temsil eden bunlardan birini döndürür. Rust arka ucu, NDK ile aynı istisna kodu değerlerini kullanır, ancak bunları kullanıcıya teslim etmeden önce yerel Rust hatalarına ( StatusCode , ExceptionCode ) dönüştürür. Hizmete özgü hatalar için döndürülen Status veya EX_SERVICE_SPECIFIC , kullanıcı tanımlı hatayla birlikte ScopedAStatus kullanır.

Yerleşik hata türleri aşağıdaki dosyalarda bulunabilir:

arka uç Tanım
java android/os/Parcel.java
CPP binder/Status.h
NDK android/binder_status.h
Pas android/binder_status.h

Çeşitli arka uçları kullanma

Bu talimatlar, Android platform koduna özeldir. Bu örnekler, tanımlanmış bir tür kullanır, my.package.IFoo . Rust arka ucunun nasıl kullanılacağına ilişkin talimatlar için Android Rust Modelleri sayfasındaki Rust AIDL örneğine bakın.

Türleri içe aktarma

Tanımlanan tür bir arabirim, ayrıştırılabilir veya birleşim olabilir, onu Java'ya aktarabilirsiniz:

import my.package.IFoo;

Veya CPP arka ucunda:

#include <my/package/IFoo.h>

Veya NDK arka ucunda (ekstra aidl ad alanına dikkat edin):

#include <aidl/my/package/IFoo.h>

Veya Rust arka ucunda:

use my_package::aidl::my::package::IFoo;

Java'da yuvalanmış bir türü içe aktarabilmenize rağmen, CPP/NDK arka uçlarında kök türü için başlığı dahil etmeniz gerekir. Örneğin, my/package/IFoo.aidl ( IFoo , dosyanın kök türüdür) içinde tanımlanan iç içe geçmiş bir Bar türünü içe aktarırken, CPP arka ucu (veya <aidl/my/package/IFoo.h> ) için <my/package/IFoo.h> eklemelisiniz. NDK arka ucu için <aidl/my/package/IFoo.h> ).

Uygulama hizmetleri

Bir hizmeti uygulamak için yerel saplama sınıfından miras almanız gerekir. Bu sınıf, ciltleyici sürücüsünden gelen komutları okur ve uyguladığınız yöntemleri yürütür. Bunun gibi bir AIDL dosyanız olduğunu hayal edin:

    package my.package;
    interface IFoo {
        int doFoo();
    }

Java'da, bu sınıftan genişletmeniz gerekir:

    import my.package.IFoo;
    public class MyFoo extends IFoo.Stub {
        @Override
        int doFoo() { ... }
    }

CPP arka ucunda:

    #include <my/package/BnFoo.h>
    class MyFoo : public my::package::BnFoo {
        android::binder::Status doFoo(int32_t* out) override;
    }

NDK arka ucunda (ekstra aidl ad alanına dikkat edin):

    #include <aidl/my/package/BnFoo.h>
    class MyFoo : public aidl::my::package::BnFoo {
        ndk::ScopedAStatus doFoo(int32_t* out) override;
    }

Rust arka ucunda:

    use aidl_interface_name::aidl::my::package::IFoo::{BnFoo, IFoo};
    use binder;

    /// This struct is defined to implement IRemoteService AIDL interface.
    pub struct MyFoo;

    impl Interface for MyFoo {}

    impl IFoo for MyFoo {
        fn doFoo(&self) -> binder::Result<()> {
           ...
           Ok(())
        }
    }

Kayıt olma ve hizmet alma

Android platformundaki hizmetler genellikle servicemanager yöneticisi işlemiyle kaydedilir. Aşağıdaki API'lere ek olarak, bazı API'ler hizmeti kontrol eder (yani hizmet mevcut değilse hemen geri dönerler). Kesin ayrıntılar için ilgili servicemanager yöneticisi arayüzünü kontrol edin. Bu işlemler yalnızca platform Android'e karşı derlenirken yapılabilir.

Java'da:

    import android.os.ServiceManager;
    // registering
    ServiceManager.addService("service-name", myService);
    // return if service is started now
    myService = IFoo.Stub.asInterface(ServiceManager.checkService("service-name"));
    // waiting until service comes up (new in Android 11)
    myService = IFoo.Stub.asInterface(ServiceManager.waitForService("service-name"));
    // waiting for declared (VINTF) service to come up (new in Android 11)
    myService = IFoo.Stub.asInterface(ServiceManager.waitForDeclaredService("service-name"));

CPP arka ucunda:

    #include <binder/IServiceManager.h>
    // registering
    defaultServiceManager()->addService(String16("service-name"), myService);
    // return if service is started now
    status_t err = checkService<IFoo>(String16("service-name"), &myService);
    // waiting until service comes up (new in Android 11)
    myService = waitForService<IFoo>(String16("service-name"));
    // waiting for declared (VINTF) service to come up (new in Android 11)
    myService = waitForDeclaredService<IFoo>(String16("service-name"));

NDK arka ucunda (ekstra aidl ad alanına dikkat edin):

    #include <android/binder_manager.h>
    // registering
    status_t err = AServiceManager_addService(myService->asBinder().get(), "service-name");
    // return if service is started now
    myService = IFoo::fromBinder(SpAIBinder(AServiceManager_checkService("service-name")));
    // is a service declared in the VINTF manifest
    // VINTF services have the type in the interface instance name.
    bool isDeclared = AServiceManager_isDeclared("android.hardware.light.ILights/default");
    // wait until a service is available (if isDeclared or you know it's available)
    myService = IFoo::fromBinder(SpAIBinder(AServiceManager_waitForService("service-name")));

Rust arka ucunda:

use myfoo::MyFoo;
use binder;
use aidl_interface_name::aidl::my::package::IFoo::BnFoo;

fn main() {
    binder::ProcessState::start_thread_pool();
    // [...]
    let my_service = MyFoo;
    let my_service_binder = BnFoo::new_binder(
        my_service,
        BinderFeatures::default(),
    );
    binder::add_service("myservice", my_service_binder).expect("Failed to register service?");
    // Does not return - spawn or perform any work you mean to do before this call.
    binder::ProcessState::join_thread_pool()
}

Bağlayıcı barındıran bir hizmet öldüğünde bildirim almak için istekte bulunabilirsiniz. Bu, geri arama proxy'lerinin sızmasını önlemeye veya hata düzeltmeye yardımcı olabilir. Bu aramaları bağlayıcı proxy nesneleri üzerinde yapın.

  • Java'da android.os.IBinder::linkToDeath kullanın.
  • CPP arka android::IBinder::linkToDeath .
  • NDK arka ucunda, AIBinder_linkToDeath kullanın.
  • Rust arka ucunda bir DeathRecipient nesnesi oluşturun, ardından my_binder.link_to_death(&mut my_death_recipient) . Geri aramanın sahibi DeathRecipient olduğu için, bildirim almak istediğiniz sürece o nesneyi canlı tutmanız gerektiğini unutmayın.

Arayan bilgisi

Bir çekirdek bağlayıcı çağrısı alırken, arayan bilgisi birkaç API'de bulunur. PID (veya İşlem Kimliği), işlem gönderen işlemin Linux işlem kimliğini ifade eder. UID (veya Kullanıcı Kimliği), Linux kullanıcı kimliğini ifade eder. Tek yönlü bir çağrı alırken, arayan PID 0'dır. Bağlayıcı işlem bağlamının dışındayken, bu işlevler geçerli sürecin PID'sini ve UID'sini döndürür.

Java arka ucunda:

    ... = Binder.getCallingPid();
    ... = Binder.getCallingUid();

CPP arka ucunda:

    ... = IPCThreadState::self()->getCallingPid();
    ... = IPCThreadState::self()->getCallingUid();

NDK arka ucunda:

    ... = AIBinder_getCallingPid();
    ... = AIBinder_getCallingUid();

Rust arka ucunda, arabirimi uygularken aşağıdakileri belirtin (varsayılan olmasına izin vermek yerine):

    ... = ThreadState::get_calling_pid();
    ... = ThreadState::get_calling_uid();

Hizmetler için hata raporları ve hata ayıklama API'si

Hata raporları çalıştırıldığında (örneğin, adb bugreport ile), çeşitli sorunların hatalarını gidermeye yardımcı olmak için sistemin her yerinden bilgi toplarlar. dumpsys hizmetleri için hata raporları, bilgilerini hata raporuna dökmek için hizmet yöneticisine kayıtlı tüm hizmetlerde ikili döküm sistemlerini kullanır. dumpsys SERVICE [ARGS] ile bir hizmetten bilgi almak için komut dumpsys de kullanabilirsiniz. C++ ve Java arka uçlarında, addService için ek bağımsız değişkenler kullanarak hizmetlerin boşaltılma sırasını kontrol edebilirsiniz. Hata ayıklama sırasında bir hizmetin PID'sini almak için dumpsys --pid SERVICE de kullanabilirsiniz.

Hizmetinize özel çıktı eklemek için, bir AIDL dosyasında tanımlanan diğer herhangi bir IPC yöntemini uyguluyormuşsunuz gibi, sunucu nesnenizdeki dump yöntemini geçersiz kılabilirsiniz. Bunu yaparken, android.permission.DUMP uygulama izniyle veya belirli UID'lerle sınırlandırmalısınız.

Java arka ucunda:

    @Override
    protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
        @Nullable String[] args) {...}

CPP arka ucunda:

    status_t dump(int, const android::android::Vector<android::String16>&) override;

NDK arka ucunda:

    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;

Rust arka ucunda, arabirimi uygularken aşağıdakileri belirtin (varsayılan olmasına izin vermek yerine):

    fn dump(&self, mut file: &File, args: &[&CStr]) -> binder::Result<()>

Arayüz tanımlayıcısını dinamik olarak alma

Arayüz tanımlayıcısı, bir arayüzün tipini tanımlar. Bu, hata ayıklarken veya bilinmeyen bir klasörünüz olduğunda kullanışlıdır.

Java'da, arayüz tanımlayıcısını aşağıdaki gibi bir kodla alabilirsiniz:

    service = /* get ahold of service object */
    ... = service.asBinder().getInterfaceDescriptor();

CPP arka ucunda:

    service = /* get ahold of service object */
    ... = IInterface::asBinder(service)->getInterfaceDescriptor();

NDK ve Rust arka uçları bu işlevi desteklemez.

Arayüz tanımlayıcısını statik olarak alma

Bazen ( @VintfStability servislerine kaydolurken olduğu gibi), arayüz tanımlayıcısının statik olarak ne olduğunu bilmeniz gerekir. Java'da, tanımlayıcıyı aşağıdaki gibi kod ekleyerek alabilirsiniz:

    import my.package.IFoo;
    ... IFoo.DESCRIPTOR

CPP arka ucunda:

    #include <my/package/BnFoo.h>
    ... my::package::BnFoo::descriptor

NDK arka ucunda (ekstra aidl ad alanına dikkat edin):

    #include <aidl/my/package/BnFoo.h>
    ... aidl::my::package::BnFoo::descriptor

Rust arka ucunda:

    aidl::my::package::BnFoo::get_descriptor()

Enum Aralığı

Yerel arka uçlarda, bir numaralandırmanın alabileceği olası değerleri yineleyebilirsiniz. Kod boyutu hususları nedeniyle bu, şu anda Java'da desteklenmemektedir.

MyEnum tanımlanan bir enum MyEnum için iterasyon aşağıdaki gibi sağlanır.

CPP arka ucunda:

    ::android::enum_range<MyEnum>()

NDK arka ucunda:

   ::ndk::enum_range<MyEnum>()

Rust arka ucunda:

    MyEnum::enum_range()

Konu yönetimi

Bir süreçteki her libbinder örneği bir iş parçacığı havuzunu korur. Çoğu kullanım durumu için bu, tüm arka uçlarda paylaşılan tam olarak bir iş parçacığı havuzu olmalıdır. Bunun tek istisnası, satıcı kodunun /dev/vndbinder ile konuşmak için başka bir libbinder kopyası yükleyebileceği zamandır. Bu, ayrı bir bağlayıcı düğümde olduğundan, iş parçacığı havuzu paylaşılmaz.

Java arka ucu için, iş parçacığı havuzunun boyutu yalnızca artabilir (çünkü zaten başlatılmıştır):

    BinderInternal.setMaxThreads(<new larger value>);

CPP arka ucu için aşağıdaki işlemler mevcuttur:

    // set max threadpool count (default is 15)
    status_t err = ProcessState::self()->setThreadPoolMaxThreadCount(numThreads);
    // create threadpool
    ProcessState::self()->startThreadPool();
    // add current thread to threadpool (adds thread to max thread count)
    IPCThreadState::self()->joinThreadPool();

Benzer şekilde, NDK arka ucunda:

    bool success = ABinderProcess_setThreadPoolMaxThreadCount(numThreads);
    ABinderProcess_startThreadPool();
    ABinderProcess_joinThreadPool();

Rust arka ucunda:

    binder::ProcessState::start_thread_pool();
    binder::add_service(“myservice”, my_service_binder).expect(“Failed to register service?”);
    binder::ProcessState::join_thread_pool();

Ayrılmış İsimler

C++, Java ve Rust bazı adları anahtar sözcük olarak veya dile özgü kullanım için ayırır. AIDL, dil kurallarına dayalı kısıtlamalar uygulamasa da, ayrılmış bir adla eşleşen alan veya tür adlarının kullanılması, C++ veya Java için derleme hatasına neden olabilir. Rust için alan veya tür, r# öneki kullanılarak erişilebilen "ham tanımlayıcı" sözdizimi kullanılarak yeniden adlandırılır.

Ergonomik olmayan bağlamalardan veya tamamen derleme hatasından kaçınmak için mümkün olduğunda AIDL tanımlarınızda ayrılmış adları kullanmaktan kaçınmanızı öneririz.

AIDL tanımlarınızda zaten ayrılmış adlarınız varsa, protokol uyumluluğunu korurken alanları güvenle yeniden adlandırabilirsiniz; oluşturmaya devam etmek için kodunuzu güncellemeniz gerekebilir, ancak önceden oluşturulmuş programlar birlikte çalışmaya devam edecektir.

Kaçınılması gereken isimler: * C++ Anahtar Kelimeleri * Java Anahtar Kelimeleri * Rust Anahtar Kelimeleri