HIDL Jawa

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

Antarmuka HIDL dimaksudkan untuk digunakan terutama dari kode asli, dan sebagai hasilnya HIDL difokuskan pada pembuatan otomatis kode efisien dalam C++. Namun, antarmuka HIDL juga harus tersedia untuk digunakan langsung dari Java, karena beberapa subsistem Android (seperti Telephony) memiliki antarmuka Java HIDL.

Halaman-halaman di bagian ini menjelaskan frontend Java untuk antarmuka HIDL, merinci cara membuat, mendaftar, dan menggunakan layanan, dan menjelaskan bagaimana klien HAL dan HAL yang ditulis dalam Java berinteraksi dengan sistem HIDL RPC.

Menjadi klien

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

Menambahkan perpustakaan

Anda perlu menambahkan dependensi pada pustaka rintisan HIDL yang sesuai jika Anda ingin menggunakannya. Biasanya, ini adalah perpustakaan 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 ketergantungan pada pustaka ini, Anda juga dapat menggunakan tautan 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 perpustakaan di Android 10

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

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

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

Basis HIDL dan pustaka pengelola juga tidak lagi tersedia di classpath boot untuk aplikasi (sebelumnya, terkadang digunakan sebagai API tersembunyi, karena pemuat kelas pertama delegasi Android). Alih-alih, mereka telah dipindahkan ke ruang nama baru dengan jarjar , dan aplikasi yang menggunakan ini (tentu saja aplikasi priv) harus memiliki salinannya sendiri yang terpisah. Modul pada classpath boot menggunakan HIDL harus menggunakan varian dangkal dari library Java ini dan menambahkan jarjar_rules: ":framework-jarjar-rules" ke Android.bp untuk menggunakan versi library ini yang ada di classpath boot.

Memodifikasi sumber Java Anda

Hanya ada satu versi ( @1.0 ) dari layanan ini, jadi kode ini hanya mengambil versi tersebut. Lihat ekstensi antarmuka untuk 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 kerangka kerja di Java mungkin perlu melayani antarmuka untuk menerima panggilan balik asinkron dari HAL.

Untuk antarmuka IFooCallback di versi 1.0 paket android.hardware.foo , Anda dapat mengimplementasikan antarmuka Anda 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 kelas abstrak android.hardware.foo.V1_0.IFooCallback.Stub , lalu tulis kelas baru untuk memperluasnya dan mengimplementasikan 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-perintah ini menghasilkan direktori /tmp/android/hardware/foo/1.0 . Untuk file hardware/interfaces/foo/1.0/IFooCallback.hal , ini menghasilkan file /tmp/android/hardware/foo/1.0/IFooCallback.java , yang merangkum antarmuka Java, kode proxy, dan stub (keduanya proxy dan stub sesuai dengan antarmuka).

-Lmakefile menghasilkan aturan yang menjalankan perintah ini pada waktu pembuatan dan memungkinkan Anda menyertakan android.hardware.foo-V1.0-java dan menautkan ke file yang sesuai. Skrip yang secara otomatis melakukan ini untuk proyek yang penuh dengan antarmuka dapat ditemukan di hardware/interfaces/update-makefiles.sh . Jalur dalam contoh ini relatif; perangkat keras/antarmuka dapat menjadi direktori sementara di bawah pohon kode Anda untuk memungkinkan Anda mengembangkan HAL sebelum menerbitkannya.

Menjalankan layanan

HAL menyediakan antarmuka IFoo , yang harus membuat panggilan balik asinkron ke kerangka kerja 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 versi 1.0 paket android.hardware.foo , tambahkan android.hardware.foo-V1.0-java ke Android.mk . Kode untuk menjalankan layanan ini 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 layanan yang diberikan mengimplementasikan antarmuka IFoo di semua perangkat, ada kemungkinan bahwa pada perangkat tertentu layanan tersebut dapat memberikan kemampuan tambahan yang diimplementasikan dalam ekstensi antarmuka IBetterFoo , sebagai berikut:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

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