Android 8.0'da Android OS, cihaza bağımsız Android platformu ile cihaza ve tedarikçiye özel kod arasında net arayüzler tanımlayacak şekilde yeniden tasarlandı. Android, bu tür birçok arayüzü HAL arayüzleri biçiminde tanımlamıştır. Bu arayüzler hardware/libhardware
'te C üstbilgileri olarak tanımlanır. HIDL, bu HAL arayüzlerini Java'da (aşağıda açıklanmıştır) veya C++'ta istemci ve sunucu tarafı HIDL arayüzleri olabilecek kararlı, sürümlü arayüzlerle değiştirdi.
HIDL arayüzlerinin öncelikle yerel koddan kullanılması amaçlandığından HIDL, C++'da verimli kodun otomatik olarak oluşturulmasına odaklanır. Ancak bazı Android alt sistemlerinde (ör. Telephony) Java HIDL arayüzleri bulunduğundan HIDL arayüzleri doğrudan Java'dan da kullanılabilir olmalıdır.
Bu bölümdeki sayfalarda, HIDL arayüzleri için Java ön ucu açıklanmakta, hizmetlerin nasıl oluşturulacağı, kaydedileceği ve kullanılacağı ayrıntılı olarak açıklanmakta ve Java'da yazılmış HAL'lerin ve HAL istemcilerinin HIDL RPC sistemiyle nasıl etkileşime geçtiği açıklanmaktadır.
İstemci örneği
Bu, android.hardware.foo@1.0
paketinde default
hizmet adı olarak kayıtlı bir IFoo
arayüzü ve second_impl
özel hizmet adıyla ek bir hizmet için istemci örneğidir.
Kitaplık ekleme
Kullanmak istiyorsanız ilgili HIDL stub kitaplığına bağımlılıklar eklemeniz gerekir. Bu genellikle statik bir kitaplıktır:
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
Bu kitaplıklara ait bağımlılıkları zaten dahil ettiğinizi biliyorsanız paylaşılan bağlantıyı da kullanabilirsiniz:
// in Android.bp libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
Android 10'da kitaplık eklemeyle ilgili ek noktalar
Android 10 veya sonraki sürümleri hedefleyen bir sistem ya da tedarikçi uygulaması varsa bu kitaplıkları statik olarak dahil edebilirsiniz. Ayrıca, sistem uygulamaları için mevcut uses-library
mekanizması kullanılarak kullanıma sunulan kararlı Java API'leriyle cihaza yüklenen özel JAR'lardan (yalnızca) HIDL sınıflarını da kullanabilirsiniz. İkinci yaklaşım, cihazda yer tasarrufu sağlar. Daha fazla bilgi için Java SDK Kitaplığını Uygulama başlıklı makaleyi inceleyin. Eski uygulamalarda eski davranış korunur.
Android 10'dan itibaren bu kitaplıkların "sığ" sürümleri de kullanılabilir. Bunlar, söz konusu sınıfı içerir ancak bağımlı sınıfları içermez. Örneğin, android.hardware.foo-V1.0-java-shallow
, foo paketindeki sınıfları içerir ancak tüm HIDL arayüzlerinin temel sınıfını içeren android.hidl.base-V1.0-java
'deki sınıfları içermez. Tercih edilen arayüzün temel sınıflarını bağımlı olarak içeren bir kitaplık oluşturuyorsanız aşağıdakileri kullanabilirsiniz:
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java-shallow", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow
HIDL temel ve yönetici kitaplıkları artık uygulamaların önyükleme sınıf yolu klasöründe de kullanılamaz (eskiden Android'in önce temsilci sınıf yükleyicisi olması nedeniyle bazen gizli API olarak kullanılıyordu). Bunun yerine, jarjar
ile yeni bir ad alanına taşındılar ve bunları kullanan uygulamaların (mutlaka özel uygulamalar) kendi ayrı kopyaları olmalıdır. HIDL kullanan önyükleme sınıf yolu üzerindeki modüller, bu Java kitaplıklarının sığ varyantlarını kullanmalıdır ve bu kitaplıkların önyükleme sınıf yolu üzerinde bulunan sürümünü kullanmak için jarjar_rules: ":framework-jarjar-rules"
değerini Android.bp
değerine eklemelidir.
Java kaynağınızı değiştirme
Bu hizmetin yalnızca bir sürümü (@1.0
) olduğundan bu kod yalnızca bu sürümü alır. Hizmetin birden fazla farklı sürümünü nasıl ele alacağınızı öğrenmek için arayüz uzantılarına bakın.
import android.hardware.foo.V1_0.IFoo; ... // retry to wait until the service starts up if it is in the manifest IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IFoo anotherServer = IFoo.getService("second_impl", true /* retry */); server.doSomething(…);
Hizmet sunma
Java'daki çerçeve kodunun, HAL'lerden asenkron geri çağırma almak için arayüz sunması gerekebilir.
android.hardware.foo
paketinin 1.0 sürümündeki IFooCallback
arayüzü için aşağıdaki adımları uygulayarak arayüzünüzü Java'da uygulayabilirsiniz:
- HIDL'de arayüzünüzü tanımlayın.
- Referans olarak
/tmp/android/hardware/foo/IFooCallback.java
dosyasını açın. - Java uygulamanız için yeni bir modül oluşturun.
- Soyut sınıf
android.hardware.foo.V1_0.IFooCallback.Stub
'ü inceleyin, ardından sınıfı genişletmek ve soyut yöntemleri uygulamak için yeni bir sınıf yazın.
Otomatik olarak oluşturulan dosyaları görüntüleme
Otomatik olarak oluşturulan dosyaları görüntülemek için şu komutu çalıştırın:
hidl-gen -o /tmp -Ljava \ -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0
Bu komutlar /tmp/android/hardware/foo/1.0
dizinini oluşturur. Bu işlem, hardware/interfaces/foo/1.0/IFooCallback.hal
dosyası için Java arayüzünü, proxy kodunu ve stub'ları (hem proxy hem de stub'lar arayüze uygundur) kapsayan /tmp/android/hardware/foo/1.0/IFooCallback.java
dosyasını oluşturur.
-Lmakefile
, derleme sırasında bu komutu çalıştıran kuralları oluşturur ve android.hardware.foo-V1.0-java
eklemenize ve uygun dosyalara bağlamanıza olanak tanır. Arayüzlerle dolu bir proje için bunu otomatik olarak yapan bir komut dosyasını hardware/interfaces/update-makefiles.sh
adresinde bulabilirsiniz.
Bu örnekteki yollar görecelidir; donanım/arayüzler, HAL'i yayınlamadan önce geliştirmenizi sağlamak için kod ağacınızdaki geçici bir dizin olabilir.
Hizmet çalıştırma
HAL, IFoo
arayüzünü sağlar. Bu arayüz, IFooCallback
arayüzü üzerinden çerçeveye asenkron geri çağırma çağrıları yapmalıdır. IFooCallback
arayüzü, bulunabilir bir hizmet olarak ada göre kaydedilmez. Bunun yerine, IFoo
, setFooCallback(IFooCallback x)
gibi bir yöntem içermelidir.
android.hardware.foo
paketinin 1.0 sürümünden IFooCallback
'ü ayarlamak için Android.mk
'a android.hardware.foo-V1.0-java
ekleyin. Hizmeti çalıştırmak için gereken kod:
import android.hardware.foo.V1_0.IFoo; import android.hardware.foo.V1_0.IFooCallback.Stub; .... class FooCallback extends IFooCallback.Stub { // implement methods } .... // Get the service from which you will be receiving callbacks. // This also starts the threadpool for your callback service. IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available .... // This must be a persistent instance variable, not local, // to avoid premature garbage collection. FooCallback mFooCallback = new FooCallback(); .... // Do this once to create the callback service and tell the "foo-bar" service server.setFooCallback(mFooCallback);
Arayüz uzantıları
Belirli bir hizmetin tüm cihazlarda IFoo
arayüzünü uyguladığı varsayıldığında, hizmetin belirli bir cihazda arayüz uzantısı IBetterFoo
'te uygulanan ek özellikleri sağlayabilmesi mümkündür. Bu özellikler şunlardır:
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
Genişletilmiş arayüzden haberdar olan kod çağırma işlemi, temel arayüzü genişletilmiş arayüze güvenli bir şekilde yayınlamak için castFrom()
Java yöntemini kullanabilir:
IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IBetterFoo extendedService = IBetterFoo.castFrom(baseService); if (extendedService != null) { // The service implements the extended interface. } else { // The service implements only the base interface. }