HIDL Java

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

Antarmuka HIDL dimaksudkan untuk digunakan terutama dari kode native, dan sebagai hasil HIDL difokuskan pada pembuatan otomatis kode efisien dalam C++. Namun, Antarmuka HIDL juga harus tersedia untuk digunakan langsung dari Java, karena beberapa Android subsistem (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 HAL klien yang ditulis dalam Java berinteraksi dengan sistem HIDL RPC.

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 Anda 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 pustaka ini, Anda juga bisa 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 Anda memiliki aplikasi sistem atau vendor yang menargetkan Android 10 atau yang lebih tinggi, Anda dapat menyertakan pustaka-pustaka ini ({i>library<i}) secara statis. Anda juga dapat menggunakan (hanya) kelas HIDL dari JAR kustom yang diinstal di perangkat dengan API Java stabil yang tersedia menggunakan mekanisme uses-library yang ada untuk aplikasi sistem. Tujuan pendekatan yang kedua akan menghemat ruang penyimpanan di perangkat. Untuk detail selengkapnya, lihat Mengimplementasikan Library Java SDK. Sebagai aplikasi yang lebih lama, perilaku lama tetap dipertahankan.

Mulai Android 10, "dangkal" versi dari library ini juga tersedia. Ini termasuk kelas yang dimaksud, tetapi tidak menyertakan dari class dependen. Contohnya, android.hardware.foo-V1.0-java-shallow menyertakan class di foo tetapi tidak menyertakan class dalam android.hidl.base-V1.0-java, yang berisi class dasar dari semua Antarmuka HIDL. Jika Anda membuat library yang sudah memiliki opsi yang tersedia sebagai dependensi, Anda dapat menggunakan kode 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 saat booting classpath untuk aplikasi (sebelumnya, mereka kadang-kadang digunakan sebagai API tersembunyi, karena classloader delegasi Android). Sebaliknya, mereka telah dipindahkan ke namespace dengan jarjar, dan aplikasi yang menggunakannya (harus sebelum aplikasi) harus memiliki salinannya sendiri yang terpisah. Modul pada classpath booting menggunakan HIDL harus menggunakan varian dangkal dari library Java ini dan menambahkan jarjar_rules: ":framework-jarjar-rules" ke Android.bp untuk menggunakan versi library yang ada di classpath booting.

Mengubah sumber Java

Hanya ada satu versi (@1.0) untuk layanan ini, jadi 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 menyajikan antarmuka untuk menerima callback dari HAL.

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

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

Lihat 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, tindakan ini akan menghasilkan file /tmp/android/hardware/foo/1.0/IFooCallback.java, yang melakukan enkapsulasi antarmuka Java, kode {i>proxy<i}, dan stub (baik {i>proxy<i} maupun stub yang sesuai dengan antarmuka).

-Lmakefile membuat aturan yang menjalankan perintah ini di build waktu dan memungkinkan Anda untuk menyertakan android.hardware.foo-V1.0-java dan tautkan 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 bersifat relatif; hardware/antarmuka dapat bersifat sementara di bawah hierarki kode agar Anda dapat mengembangkan HAL sebelum memublikasikannya.

Menjalankan layanan

HAL menyediakan antarmuka IFoo, yang harus membuat callback ke framework melalui antarmuka IFooCallback. Tujuan Antarmuka IFooCallback tidak terdaftar dengan nama sebagai antarmuka yang dapat ditemukan layanan; 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 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 tertentu mengimplementasikan antarmuka IFoo di semua di perangkat tertentu, layanan itu mungkin menyediakan kemampuan tambahan yang diimplementasikan dalam ekstensi antarmuka IBetterFoo, sebagai berikut:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Memanggil kode yang menyadari antarmuka yang diperluas bisa menggunakan Metode Java castFrom() untuk mentransmisikan antarmuka dasar dengan aman ke antarmuka yang diperluas:

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