HIDL Java

Android 8.0'da Android işletim sistemi, cihazdan bağımsız Android platformu ile cihaza ve satıcıya özel kod arasında net arayüzler tanımlamak için yeniden tasarlandı. Android, hardware/libhardware C başlıkları olarak tanımlanan HAL arabirimleri biçiminde bu tür birçok arabirimi zaten tanımladı. HIDL, bu HAL arabirimlerini, Java'da olabilen (aşağıda açıklanmıştır) veya C++' da istemci ve sunucu tarafı HIDL arabirimleri olabilen kararlı, sürümlü arabirimlerle değiştirdi.

HIDL arabirimlerinin öncelikle yerel koddan kullanılması amaçlanmıştır ve sonuç olarak HIDL, C++'da verimli kodun otomatik olarak oluşturulmasına odaklanır. Ancak, bazı Android alt sistemlerinde (Telephony gibi) Java HIDL arabirimleri bulunduğundan, HIDL arabirimlerinin doğrudan Java'dan kullanım için de mevcut olması gerekir.

Bu bölümdeki sayfalar, HIDL arabirimleri için Java ön ucunu açıklar, hizmetlerin nasıl oluşturulacağını, kaydedileceğini ve kullanılacağını ayrıntılı olarak açıklar ve Java ile yazılmış HAL'lerin ve HAL istemcilerinin HIDL RPC sistemi ile nasıl etkileşime girdiğini açıklar.

müşteri olmak

Bu, hizmet adı default olarak kayıtlı olan android.hardware.foo@1.0 paketindeki IFoo arabirimi için bir istemci ve second_impl özel hizmet adıyla ek bir hizmet örneğidir.

Kitaplık ekleme

Kullanmak istiyorsanız, ilgili HIDL saplama kitaplığına bağımlılıklar eklemeniz gerekir. Genellikle, bu 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 zaten bağımlılıklar çektiğ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 hususlar

Android 10 veya üstünü hedefleyen bir sistem veya satıcı uygulamanız varsa, bu kitaplıkları statik olarak dahil edebilirsiniz. Ayrıca (yalnızca) sistem uygulamaları için mevcut uses-library mekanizması kullanılarak sağlanan kararlı Java API'leri ile cihaza yüklenen özel JAR'lardan HIDL sınıflarını da kullanabilirsiniz. İkinci yaklaşım, cihazda yerden tasarruf sağlar. Daha fazla ayrıntı için bkz. Java SDK Kitaplığını Uygulama . Daha eski uygulamalar için eski davranış korunur.

Android 10'dan başlayarak, bu kitaplıkların "sığ" sürümleri de mevcuttur. Bunlar, söz konusu sınıfı içerir ancak bağımlı sınıfların hiçbirini içermez. Örneğin, android.hardware.foo-V1.0-java-shallow , foo paketindeki sınıfları içerir, ancak tüm HIDL'lerin temel sınıfını içeren android.hidl.base-V1.0-java içindeki sınıfları içermez. arayüzler. Tercih edilen arabirimin bağımlılık olarak kullanılabilen temel sınıflarına sahip 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 için önyükleme sınıf yolunda mevcut değildir (önceden, Android'in temsilci birinci sınıf yükleyicisi nedeniyle bazen gizli API olarak kullanılıyorlardı). 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 yolundaki modüller, bu Java kitaplıklarının sığ türevlerini kullanmalı ve bu kitaplıkların önyükleme sınıf yolunda bulunan sürümünü kullanmak için Android.bp jarjar_rules: ":framework-jarjar-rules" eklemelidir.

Java kaynağınızı değiştirme

Bu hizmetin yalnızca bir sürümü ( @1.0 ) vardır, bu nedenle bu kod yalnızca o sürümü alır. Hizmetin birden çok farklı sürümünün nasıl ele alınacağını öğrenmek için arabirim 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 sağlamak

Java'daki çerçeve kodunun, HAL'lerden eşzamansız geri aramaları almak için arabirimler sunması gerekebilir.

android.hardware.foo paketinin 1.0 sürümündeki IFooCallback arabirimi için, aşağıdaki adımları kullanarak arabiriminizi Java'da uygulayabilirsiniz:

  1. Arayüzünüzü HIDL'de tanımlayın.
  2. Referans olarak /tmp/android/hardware/foo/IFooCallback.java açın.
  3. Java uygulamanız için yeni bir modül oluşturun.
  4. android.hardware.foo.V1_0.IFooCallback.Stub soyut sınıfını inceleyin, ardından onu genişletmek ve soyut yöntemleri uygulamak için yeni bir sınıf yazın.

Otomatik oluşturulan dosyaları görüntüleme

Otomatik olarak oluşturulan dosyaları görüntülemek için şunu ç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. hardware/interfaces/foo/1.0/IFooCallback.hal dosyası için bu, Java arabirimini, proxy kodunu ve taslakları (her ikisi de proxy) içine alan /tmp/android/hardware/foo/1.0/IFooCallback.java dosyasını oluşturur. ve taslaklar arayüze uygundur).

-Lmakefile , bu komutu derleme zamanında çalıştıran ve android.hardware.foo-V1.0-java eklemenize ve uygun dosyalara bağlantı vermenize izin veren kuralları oluşturur. Arayüzlerle dolu bir proje için bunu otomatik olarak yapan bir komut dosyası, hardware/interfaces/update-makefiles.sh . Bu örnekteki yollar görecelidir; donanım/arayüzler, yayınlamadan önce bir HAL geliştirmenizi sağlamak için kod ağacınızın altındaki geçici bir dizin olabilir.

Bir hizmeti çalıştırma

HAL, IFoo arabirimi üzerinden çerçeveye zaman uyumsuz geri aramalar yapması gereken IFooCallback arabirimini sağlar. IFooCallback arabirimi, keşfedilebilir bir hizmet olarak adıyla kayıtlı değildir; bunun yerine, IFoo setFooCallback(IFooCallback x) gibi bir yöntem içermelidir.

android.hardware.foo paketinin 1.0 sürümünden IFooCallback'i kurmak için IFooCallback dosyasına android.hardware.foo-V1.0-java Android.mk . Hizmeti çalıştırmak için kod şudur:

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 aygıtlarda IFoo arabirimini uyguladığını varsayarsak, hizmetin belirli bir aygıtta IBetterFoo arabirim uzantısında uygulanan ek yetenekleri aşağıdaki gibi sağlaması mümkündür:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Genişletilmiş arabirimden haberdar olan çağrı kodu, temel arabirimi genişletilmiş arabirime 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.
}