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 zaten hardware/libhardware C başlıkları olarak tanımlanan HAL arayüzleri biçiminde bu tür birçok arayüzü tanımladı. HIDL, bu HAL arayüzlerini, Java'da (aşağıda açıklanmıştır) veya C++ 'da istemci ve sunucu tarafı HIDL arayüzleri olabilen kararlı, sürümlü arayüzlerle değiştirdi.

HIDL arayüzlerinin öncelikle yerel koddan kullanılması amaçlanmıştır ve sonuç olarak HIDL, C++'ta verimli kodun otomatik olarak oluşturulmasına odaklanır. Bununla birlikte, bazı Android alt sistemlerinde (Telefon gibi) Java HIDL arayüzleri bulunduğundan, HIDL arayüzlerinin doğrudan Java'dan kullanıma sunulması gerekir.

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ılarıyla anlatılmakta ve Java'da yazılan HAL'lerin ve HAL istemcilerinin HIDL RPC sistemiyle nasıl etkileşime girdiği açıklanmaktadır.

Müşteri olmak

Bu, default hizmet adı olarak kaydedilen android.hardware.foo@1.0 paketindeki IFoo arayüzüne ve second_impl özel hizmet adına sahip ek bir hizmete yönelik bir istemci örneğidir.

Kitaplıklar ekleme

Kullanmak istiyorsanız ilgili HIDL saplama kitaplığına bağımlılıklar eklemeniz gerekir. Genellikle bu statik bir kütüphanedir:

// 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 getirdiğ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, sistem uygulamaları için mevcut uses-library mekanizması kullanılarak kullanıma sunulan kararlı Java API'leri ile cihaza yüklenen özel JAR'lardaki (yalnızca) 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 uygulamalarda eski davranış korunur.

Android 10'dan itibaren 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 arayüzün temel sınıflarının bağımlılık olarak zaten mevcut olduğu 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 tabanı ve yönetici kitaplıkları da artık uygulamalar için önyükleme sınıf yolunda mevcut değildir (daha önce, Android'in ilk temsilci 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ına sahip olması gerekiyor. HIDL kullanan önyükleme sınıf yolundaki modüller, bu Java kitaplıklarının sığ değişkenlerini 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 ) olduğundan bu kod yalnızca bu sürümü alır. Hizmetin birden çok farklı sürümünün nasıl işleneceğini öğ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 sunmak

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

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

  1. Arayüzünüzü HIDL'de 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. 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 olarak 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 arayüzünü, proxy kodunu ve saplamaları (her ikisi de proxy) kapsülleyen /tmp/android/hardware/foo/1.0/IFooCallback.java dosyasını oluşturur. ve saplamalar arayüze uygundur).

-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ğlantı vermenize olanak tanır. Arayüzlerle dolu bir proje için bunu otomatik olarak yapan bir komut dosyası, hardware/interfaces/update-makefiles.sh adresinde bulunabilir. Bu örnekteki yollar görecelidir; donanım/arayüzler, kod ağacınızın altında, yayınlamadan önce bir HAL geliştirmenize olanak tanıyan geçici bir dizin olabilir.

Bir hizmeti çalıştırma

HAL, IFooCallback arayüzü üzerinden çerçeveye eşzamansız geri aramalar yapması gereken IFoo arayüzünü sağlar. IFooCallback arayüzü keşfedilebilir bir hizmet olarak isme göre kayıtlı değildir; bunun yerine IFoo setFooCallback(IFooCallback x) gibi bir yöntem içermesi gerekir.

IFooCallback android.hardware.foo paketinin 1.0 sürümünden ayarlamak için android.hardware.foo-V1.0-java Android.mk dosyasına ekleyin. Hizmeti çalıştıracak 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 IFoo arayüzünü tüm cihazlarda uyguladığını varsayarsak, belirli bir cihazda hizmetin IBetterFoo arayüz uzantısında aşağıdaki gibi uygulanan ek yetenekleri sağlaması mümkündür:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Genişletilmiş arayüzün farkında olarak kod çağırmak, temel arayüzü genişletilmiş arayüze güvenli bir şekilde aktarmak 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.
}