Setiap antarmuka yang ditentukan dalam paket HIDL memiliki class C++ buatan sendiri di dalam namespace paketnya. Klien dan server menangani antarmuka dengan cara yang berbeda:
- Server menerapkan antarmuka.
- Klien memanggil metode di antarmuka.
Antarmuka dapat didaftarkan menurut nama oleh server atau diteruskan sebagai parameter ke metode yang ditentukan HIDL. Misalnya, kode framework dapat menyalurkan antarmuka untuk menerima pesan asinkron dari HAL dan meneruskan antarmuka tersebut 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 diekspor secara otomatis oleh library bersama
antarmuka IFoo
untuk ditautkan. Contoh IFoo.hal
:
// IFoo.hal interface IFoo { someMethod() generates (vec<uint32_t>); ... }
Contoh kerangka untuk penerapan 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(); } ... };
Agar implementasi antarmuka server tersedia untuk klien, Anda dapat:
- Daftarkan implementasi antarmuka dengan
hwservicemanager
(lihat detail di bawah),
ATAU
- Teruskan implementasi antarmuka sebagai argumen metode antarmuka (untuk mengetahui detailnya, lihat Callback asinkron).
Saat mendaftarkan implementasi antarmuka, proses hwservicemanager
melacak antarmuka HIDL terdaftar
yang berjalan di perangkat berdasarkan nama dan versi. Server dapat mendaftarkan implementasi antarmuka HIDL berdasarkan nama dan klien dapat meminta implementasi layanan berdasarkan nama dan versi. Proses ini menayangkan antarmuka HIDL
android.hidl.manager@1.0::IServiceManager
.
Setiap file header antarmuka HIDL yang dibuat otomatis (seperti IFoo.h
)
memiliki metode registerAsService()
yang dapat digunakan untuk mendaftarkan
implementasi antarmuka dengan hwservicemanager
. Satu-satunya
argumen yang diperlukan adalah nama implementasi antarmuka karena klien
menggunakan 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 memungkinkan
antarmuka yang berbeda (atau versi antarmuka yang sama) mendaftar
dengan nama instance yang identik tanpa konflik. Jika Anda memanggil
registerAsService()
dengan versi paket, antarmuka,
dan nama instance yang sama persis, hwservicemanager
akan menghapus referensinya ke
layanan yang terdaftar sebelumnya dan menggunakan layanan baru.
Implementasi klien
Sama seperti server, klien harus #include
setiap antarmuka
yang dirujuknya:
#include <android/hardware/samples/1.0/IFoo.h>
Klien dapat memperoleh antarmuka dengan dua cara:
- Melalui
I<InterfaceName>::getService
(melaluihwservicemanager
) - Melalui metode antarmuka
Setiap file header antarmuka yang dibuat secara otomatis memiliki metode 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 ke
antarmuka tersebut seolah-olah itu adalah implementasi class lokal. Pada kenyataannya, penerapan
dapat berjalan dalam proses yang sama, proses yang berbeda, atau bahkan di perangkat lain
(dengan remot HAL). Karena klien memanggil getService
pada
objek IFoo
yang disertakan dari versi 1.0
paket,
hwservicemanager
hanya menampilkan implementasi server jika
implementasi tersebut kompatibel dengan klien 1.0
. Dalam praktiknya, hal ini
berarti hanya implementasi server dengan versi 1.n
(versi
x.(y+1)
antarmuka harus memperluas (mewarisi dari)
x.y
).
Selain itu, metode castFrom
disediakan untuk melakukan transmisi antar-antarmuka
yang berbeda. Metode ini berfungsi dengan melakukan panggilan IPC ke antarmuka
jarak jauh untuk memastikan jenis yang mendasarinya sama dengan jenis yang
diminta. Jika jenis yang diminta tidak tersedia, nullptr
akan
ditampilkan.
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 berkomunikasi dengan hardware asinkron, yang berarti mereka memerlukan cara asinkron untuk memberi tahu klien tentang peristiwa baru yang telah terjadi. Antarmuka HIDL dapat digunakan sebagai callback asinkron karena fungsi antarmuka HIDL 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 menggunakan
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 antarmuka IFooCallback
; antarmuka 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 } };
Anda juga dapat meneruskannya melalui instance antarmuka
IFoo
yang ada:
sp<IFooCallback> myFooCallback = new FooCallback(); myFoo.registerCallback(myFooCallback);
Server yang menerapkan IFoo
menerimanya sebagai
objek sp<IFooCallback>
. Fungsi ini dapat menyimpan callback, dan memanggil
kembali ke klien setiap kali ingin menggunakan antarmuka ini.
Penerima kematian
Karena implementasi layanan dapat berjalan dalam proses yang berbeda, proses yang menerapkan antarmuka dapat berhenti sementara klien tetap aktif.
Setiap panggilan pada objek antarmuka yang dihosting dalam proses yang telah berhenti akan gagal
dengan error transpor (isOK()
menampilkan false
). Satu-satunya cara untuk
memulihkan dari kegagalan tersebut adalah dengan meminta instance layanan baru dengan
memanggil I<InterfaceName>::getService()
. Hal ini hanya berfungsi jika
proses yang mengalami error telah dimulai ulang dan mendaftarkan ulang layanannya dengan
servicemanager
(yang umumnya berlaku untuk implementasi HAL).
Daripada menanganinya secara reaktif, klien antarmuka juga dapat
mendaftarkan penerima kematian untuk mendapatkan notifikasi saat layanan mati.
Untuk mendaftar ke notifikasi tersebut di antarmuka IFoo
yang diambil, klien dapat melakukan hal berikut:
foo->linkToDeath(recipient, 1481 /* cookie */);
Parameter recipient
harus berupa implementasi
antarmuka android::hardware::hidl_death_recipient
yang disediakan oleh HIDL,
yang berisi satu metode serviceDied()
yang dipanggil
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);