HIDL Java

Di Android 8.0, Android OS dirancang ulang untuk menentukan antarmuka yang jelas antara platform Android yang tidak bergantung pada perangkat, dan kode khusus perangkat dan vendor. Android telah menentukan banyak antarmuka tersebut dalam bentuk antarmuka HAL, yang ditentukan sebagai header C di hardware/libhardware. HIDL mengganti antarmuka HAL ini dengan antarmuka berversi stabil, yang dapat berada di Java (dijelaskan di bawah) atau antarmuka HIDL sisi klien dan server di C++.

Antarmuka HIDL dimaksudkan untuk digunakan terutama dari kode native, dan sebagai akibatnya, HIDL berfokus pada pembuatan kode yang efisien secara otomatis di C++. Namun, antarmuka HIDL juga harus tersedia untuk digunakan langsung dari Java, karena beberapa subsistem Android (seperti Telepon) memiliki antarmuka HIDL Java.

Halaman di bagian ini menjelaskan frontend Java untuk antarmuka HIDL, menjelaskan cara membuat, mendaftarkan, dan menggunakan layanan, serta menjelaskan cara HAL dan klien HAL yang ditulis dalam Java berinteraksi dengan sistem RPC HIDL.

Contoh klien

Ini adalah contoh klien untuk antarmuka IFoo dalam paket android.hardware.foo@1.0 yang terdaftar sebagai nama layanan default dan layanan tambahan dengan nama layanan kustom second_impl.

Menambahkan library

Anda perlu menambahkan dependensi pada library stub HIDL yang sesuai jika ingin menggunakannya. Biasanya, ini adalah library statis:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Jika Anda tahu bahwa Anda sudah menarik dependensi pada library ini, Anda juga dapat menggunakan penautan bersama:

// in Android.bp
libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Pertimbangan tambahan untuk menambahkan library di Android 10

Jika memiliki aplikasi sistem atau vendor yang menargetkan Android 10 atau yang lebih baru, Anda dapat menyertakan library ini secara statis. Anda juga dapat menggunakan (hanya) class HIDL dari JAR kustom yang diinstal di perangkat dengan Java API stabil yang tersedia menggunakan mekanisme uses-library yang ada untuk aplikasi sistem. Pendekatan terakhir menghemat ruang di perangkat. Untuk mengetahui detail selengkapnya, lihat Mengimplementasikan Library Java SDK. Untuk aplikasi lama, perilaku lama akan dipertahankan.

Mulai Android 10, versi "dangkal" library ini juga tersedia. Ini mencakup class yang dimaksud, tetapi tidak menyertakan class dependen. Misalnya, android.hardware.foo-V1.0-java-shallow menyertakan class dalam paket foo, tetapi tidak menyertakan class dalam android.hidl.base-V1.0-java, yang berisi class dasar dari semua antarmuka HIDL. Jika membuat library yang sudah memiliki class dasar antarmuka pilihan yang tersedia sebagai dependensi, Anda dapat menggunakan hal berikut:

// 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

Library dasar dan pengelola HIDL juga tidak lagi tersedia di classpath boot untuk aplikasi (sebelumnya, library tersebut terkadang digunakan sebagai API tersembunyi, karena classloader delegasi-pertama Android). Sebagai gantinya, keduanya telah dipindahkan ke namespace baru dengan jarjar, dan aplikasi yang menggunakannya (harus aplikasi priv) harus memiliki salinan terpisahnya sendiri. Modul di classpath booting yang menggunakan HIDL harus menggunakan varian dangkal library Java ini dan menambahkan jarjar_rules: ":framework-jarjar-rules" ke Android.bp untuk menggunakan versi library ini yang ada di classpath booting.

Mengubah sumber Java

Hanya ada satu versi (@1.0) layanan ini, sehingga kode ini hanya mengambil versi tersebut. Lihat ekstensi antarmuka untuk mengetahui cara menangani beberapa versi layanan yang berbeda.

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(…);

Menyediakan layanan

Kode framework di Java mungkin perlu menayangkan antarmuka untuk menerima callback asinkron dari HAL.

Untuk antarmuka IFooCallback dalam paket android.hardware.foo versi 1.0, Anda dapat menerapkan antarmuka di Java menggunakan langkah-langkah berikut:

  1. Tentukan antarmuka Anda di HIDL.
  2. Buka /tmp/android/hardware/foo/IFooCallback.java sebagai referensi.
  3. Buat modul baru untuk implementasi Java Anda.
  4. Periksa class abstrak android.hardware.foo.V1_0.IFooCallback.Stub, lalu tulis class baru untuk memperluasnya dan menerapkan metode abstrak.

Melihat file yang dibuat secara otomatis

Untuk melihat file yang dibuat secara otomatis, jalankan:

hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0

Perintah ini menghasilkan direktori /tmp/android/hardware/foo/1.0. Untuk file hardware/interfaces/foo/1.0/IFooCallback.hal, tindakan ini akan menghasilkan file /tmp/android/hardware/foo/1.0/IFooCallback.java, yang mengaitkan antarmuka Java, kode proxy, dan stub (baik proxy maupun stub sesuai dengan antarmuka).

-Lmakefile menghasilkan aturan yang menjalankan perintah ini pada waktu build dan memungkinkan Anda menyertakan android.hardware.foo-V1.0-java dan menautkan ke file yang sesuai. Skrip yang otomatis melakukan hal ini untuk project yang penuh dengan antarmuka dapat ditemukan di hardware/interfaces/update-makefiles.sh. Jalur dalam contoh ini bersifat relatif; hardware/antarmuka dapat berupa direktori sementara di bawah hierarki kode Anda agar Anda dapat mengembangkan HAL sebelum memublikasikannya.

Menjalankan layanan

HAL menyediakan antarmuka IFoo, yang harus membuat callback asinkron ke framework melalui antarmuka IFooCallback. Antarmuka IFooCallback tidak terdaftar berdasarkan nama sebagai layanan yang dapat ditemukan; sebagai gantinya, IFoo harus berisi metode seperti setFooCallback(IFooCallback x).

Untuk menyiapkan IFooCallback dari paket android.hardware.foo versi 1.0, tambahkan android.hardware.foo-V1.0-java ke Android.mk. Kode untuk menjalankan layanan adalah:

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);

Ekstensi antarmuka

Dengan asumsi bahwa layanan tertentu menerapkan antarmuka IFoo di semua perangkat, layanan tersebut mungkin menyediakan kemampuan tambahan yang diterapkan di ekstensi antarmuka IBetterFoo, sebagai berikut:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Kode panggilan yang mengetahui antarmuka yang diperluas dapat menggunakan metode Java castFrom() untuk mentransmisikan antarmuka dasar ke antarmuka yang diperluas dengan aman:

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.
}