Setiap antarmuka yang ditentukan dalam paket HIDL memiliki class C++ yang dibuat secara otomatis di dalam namespace paketnya. Klien dan server berurusan dengan antarmuka di cara yang berbeda:
- Server menerapkan antarmuka.
- Klien memanggil metode pada antarmuka.
Antarmuka dapat didaftarkan menurut nama oleh server atau diteruskan sebagai parameter ke metode yang ditentukan HIDL. Misalnya, kode framework dapat menyajikan untuk menerima pesan asinkron dari HAL dan meneruskan antarmuka itu langsung ke HAL tanpa mendaftarkannya.
Implementasi server
Server yang menerapkan antarmuka IFoo
harus menyertakan
File header IFoo
yang dibuat secara otomatis:
#include <android/hardware/samples/1.0/IFoo.h>
Header secara otomatis diekspor oleh pustaka bersama dari
Antarmuka IFoo
yang akan ditautkan. Contoh IFoo.hal
:
// IFoo.hal interface IFoo { someMethod() generates (vec<uint32_t>); ... }
Contoh kerangka untuk implementasi server antarmuka IFoo:
// From the IFoo.h header using android::hardware::samples::V1_0::IFoo; class FooImpl : public IFoo { Return<void> someMethod(foo my_foo, someMethod_cb _cb) { vec<uint32_t> return_data; // Compute return_data _cb(return_data); return Void(); } ... };
Untuk membuat implementasi antarmuka server tersedia bagi klien, Anda dapat:
- Daftarkan implementasi antarmuka ke
hwservicemanager
(lihat detailnya di bawah),
ATAU
- Meneruskan implementasi antarmuka sebagai argumen metode antarmuka (untuk detal, lihat Asinkron callback).
Saat mendaftarkan implementasi antarmuka,
Proses hwservicemanager
melacak antarmuka HIDL yang terdaftar
yang berjalan di perangkat
berdasarkan nama dan versi. Server dapat mendaftarkan antarmuka HIDL
implementasi berdasarkan nama dan klien dapat meminta implementasi layanan berdasarkan nama
beserta versinya. Proses ini menyalurkan antarmuka HIDL
android.hidl.manager@1.0::IServiceManager
.
Setiap file header antarmuka HIDL yang dibuat secara otomatis (seperti IFoo.h
)
memiliki metode registerAsService()
yang dapat digunakan untuk mendaftarkan
implementasi antarmuka pengguna dengan hwservicemanager
. Satu-satunya
yang diperlukan adalah nama implementasi antarmuka sebagai klien
gunakan nama ini untuk mengambil antarmuka dari hwservicemanager
nanti:
::android::sp<IFoo> myFoo = new FooImpl(); ::android::sp<IFoo> mySecondFoo = new FooAnotherImpl(); status_t status = myFoo->registerAsService(); status_t anotherStatus = mySecondFoo->registerAsService("another_foo");
hwservicemanager
memperlakukan kombinasi
[package@version::interface, instance_name]
sebagai unik untuk mengaktifkan
antarmuka yang berbeda (atau versi berbeda
dari antarmuka yang sama) untuk mendaftarkan
dengan nama instance yang identik tanpa konflik. Jika Anda memanggil
registerAsService()
dengan versi paket, antarmuka, dan
dan nama instance, hwservicemanager
akan meletakkan referensinya ke
yang sebelumnya terdaftar
dan menggunakan yang baru.
Implementasi klien
Seperti yang dilakukan server, klien harus melakukan #include
setiap antarmuka
hal ini merujuk pada:
#include <android/hardware/samples/1.0/IFoo.h>
Klien dapat memperoleh antarmuka dengan dua cara:
- Sampai
I<InterfaceName>::getService
(melaluihwservicemanager
) - Melalui metode antarmuka
Setiap file header antarmuka yang dibuat secara otomatis memiliki getService
statis
yang dapat digunakan untuk mengambil instance layanan dari
hwservicemanager
:
// getService returns nullptr if the service can't be found sp<IFoo> myFoo = IFoo::getService(); sp<IFoo> myAlternateFoo = IFoo::getService("another_foo");
Sekarang klien memiliki antarmuka IFoo
, dan dapat memanggil metode untuk
seolah-olah itu adalah
implementasi kelas lokal. Pada kenyataannya, implementasi
dapat berjalan dalam proses yang sama, proses yang berbeda, atau bahkan pada perangkat lain
(dengan jarak jauh HAL). Karena klien memanggil getService
di
Objek IFoo
disertakan dari versi 1.0
paket,
hwservicemanager
menampilkan implementasi server hanya jika
kompatibel dengan klien 1.0
. Dalam praktiknya,
berarti hanya implementasi server dengan versi 1.n
(versi
x.(y+1)
antarmuka harus diperluas (diwarisi dari)
x.y
).
Selain itu, metode castFrom
disediakan untuk melakukan transmisi antara
antarmuka yang berbeda. Metode ini berfungsi dengan
membuat panggilan IPC ke {i>remote<i}
untuk memastikan tipe dasar sama dengan tipe yang sedang
diminta. Jika jenis yang diminta tidak tersedia, maka nullptr
adalah
dikembalikan.
sp<V1_0::IFoo> foo1_0 = V1_0::IFoo::getService(); sp<V1_1::IFoo> foo1_1 = V1_1::IFoo::castFrom(foo1_0);
Callback asinkron
Banyak implementasi HAL yang ada berhubungan dengan perangkat keras asinkron, yang berarti mereka membutuhkan cara asinkron untuk memberi tahu klien tentang peristiwa baru yang terjadi. Antarmuka HIDL dapat digunakan sebagai callback asinkron karena HIDL fungsi antarmuka dapat menggunakan objek antarmuka HIDL sebagai parameter.
Contoh file antarmuka IFooCallback.hal
:
package android.hardware.samples@1.0; interface IFooCallback { sendEvent(uint32_t event_id); sendData(vec<uint8_t> data); }
Contoh metode baru di IFoo
yang memerlukan
Parameter IFooCallback
:
package android.hardware.samples@1.0; interface IFoo { struct Foo { int64_t someValue; handle myHandle; }; someMethod(Foo foo) generates (int32_t ret); anotherMethod() generates (vec<uint32_t>); registerCallback(IFooCallback callback); };
Klien yang menggunakan antarmuka IFoo
adalah
server dari antarmuka IFooCallback
; model ini menyediakan
implementasi IFooCallback
:
class FooCallback : public IFooCallback { Return<void> sendEvent(uint32_t event_id) { // process the event from the HAL } Return<void> sendData(const hidl_vec<uint8_t>& data) { // process data from the HAL } };
Fungsi ini juga dapat meneruskannya ke instance yang ada dari
Antarmuka IFoo
:
sp<IFooCallback> myFooCallback = new FooCallback(); myFoo.registerCallback(myFooCallback);
Server yang menerapkan IFoo
menerima ini sebagai
Objek sp<IFooCallback>
. Ia bisa menyimpan callback, dan memanggil
kembali ke klien kapan pun ia
ingin menggunakan antarmuka ini.
Penerima kematian
Karena implementasi layanan dapat berjalan
dalam proses yang berbeda, maka hal itu dapat terjadi
bahwa proses yang mengimplementasikan antarmuka
akan mati saat klien tetap hidup.
Setiap panggilan pada objek antarmuka yang dihosting dalam proses yang telah berhenti gagal
dengan error transportasi (isOK()
menampilkan false
). Satu-satunya cara untuk
memulihkan dari kegagalan tersebut adalah
meminta {i>instance <i}layanan baru dengan
memanggil I<InterfaceName>::getService()
. Ini hanya berfungsi jika
proses yang rusak telah dimulai ulang dan
mendaftarkan ulang layanannya dengan
servicemanager
(yang umumnya berlaku untuk implementasi HAL).
Alih-alih menangani ini secara reaktif, klien antarmuka juga bisa
mendaftarkan penerima kematian untuk mendapatkan notifikasi saat layanan berhenti digunakan.
Untuk mendaftarkan notifikasi tersebut pada antarmuka IFoo
yang diambil,
klien dapat melakukan hal berikut:
foo->linkToDeath(recipient, 1481 /* cookie */);
Parameter recipient
harus berupa implementasi
android::hardware::hidl_death_recipient
yang disediakan oleh HIDL,
yang berisi satu metode serviceDied()
yang disebut
dari thread di threadpool RPC saat proses yang menghosting antarmuka berhenti:
class MyDeathRecipient : public android::hardware::hidl_death_recipient { virtual void serviceDied(uint64_t cookie, const android::wp<::android::hidl::base::V1_0::IBase>& who) { // Deal with the fact that the service died } }
Parameter cookie
berisi cookie yang diteruskan dengan
linkToDeath()
, sedangkan parameter who
berisi
pointer lemah ke objek yang mewakili layanan di klien. Dengan
contoh panggilan yang diberikan di atas, cookie
sama dengan 1481, dan who
sama dengan foo
.
Anda juga dapat membatalkan pendaftaran penerima kematian setelah mendaftarkannya:
foo->unlinkToDeath(recipient);