HIDL Java

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:

  1. HIDL'de arayüzünüzü tanımlayın.
  2. Referans olarak /tmp/android/hardware/foo/IFooCallback.java dosyasını açın.
  3. Java uygulamanız için yeni bir modül oluşturun.
  4. 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.
}