Halaman ini menjelaskan cara mendaftarkan dan menemukan layanan serta cara mengirim
data ke layanan dengan memanggil metode yang ditentukan dalam antarmuka di file
.hal
.
Mendaftar layanan
Server antarmuka HIDL (objek yang mengimplementasikan antarmuka) dapat didaftarkan sebagai layanan bernama. Nama yang terdaftar tidak harus terkait dengan antarmuka atau nama paket. Jika tidak ada nama yang ditentukan, nama "default" akan digunakan; hal ini harus digunakan untuk HAL yang tidak perlu mendaftarkan dua implementasi antarmuka yang sama. Misalnya, panggilan C++ untuk pendaftaran layanan yang ditentukan di setiap antarmuka adalah:
status_t status = myFoo->registerAsService(); status_t anotherStatus = anotherFoo->registerAsService("another_foo_service"); // if needed
Versi antarmuka HIDL disertakan dalam antarmuka itu sendiri. ID ini
otomatis dikaitkan dengan pendaftaran layanan dan dapat diambil melalui
panggilan metode (android::hardware::IInterface::getInterfaceVersion()
)
di setiap antarmuka HIDL. Objek server tidak perlu didaftarkan dan dapat diteruskan
melalui parameter metode HIDL ke proses lain yang membuat panggilan metode HIDL
ke server.
Menemukan layanan
Permintaan berdasarkan kode klien dibuat untuk antarmuka tertentu berdasarkan nama dan
versi, yang memanggil getService
pada class HAL yang diinginkan:
// C++ sp<V1_1::IFooService> service = V1_1::IFooService::getService(); sp<V1_1::IFooService> alternateService = V1_1::IFooService::getService("another_foo_service"); // Java V1_1.IFooService service = V1_1.IFooService.getService(true /* retry */); V1_1.IFooService alternateService = V1_1.IFooService.getService("another", true /* retry */);
Setiap versi antarmuka HIDL diperlakukan sebagai antarmuka terpisah. Dengan demikian,
IFooService
versi 1.1 dan IFooService
versi 2.2
dapat didaftarkan sebagai "foo_service" dan
getService("foo_service")
di salah satu antarmuka mendapatkan layanan
yang terdaftar untuk antarmuka tersebut. Itulah sebabnya, dalam sebagian besar kasus, tidak ada parameter nama yang perlu
disediakan untuk pendaftaran atau penemuan (artinya nama "default").
Objek Antarmuka Vendor juga berperan dalam metode transpor antarmuka
yang ditampilkan. Untuk antarmuka IFoo
dalam paket
android.hardware.foo@1.0
, antarmuka yang ditampilkan oleh
IFoo::getService
selalu menggunakan metode transpor yang dideklarasikan untuk
android.hardware.foo
dalam manifes perangkat jika entri ada;
dan jika metode transpor tidak tersedia, nullptr akan ditampilkan.
Dalam beberapa kasus, Anda mungkin perlu segera melanjutkan meskipun tanpa
mendapatkan layanan. Hal ini dapat terjadi (misalnya) saat klien ingin
mengelola notifikasi layanan itu sendiri atau dalam program diagnostik (seperti
atrace
) yang perlu mendapatkan semua hwservices dan mengambilnya. Dalam
hal ini, API tambahan disediakan seperti tryGetService
di C++ atau
getService("instance-name", false)
di Java. getService
API
lama yang disediakan di Java juga harus digunakan dengan notifikasi
layanan. Menggunakan API ini tidak menghindari kondisi race saat server
mendaftarkan dirinya sendiri setelah klien memintanya dengan salah satu API tanpa percobaan ulang ini.
Notifikasi penghentian layanan
Klien yang ingin diberi tahu saat layanan berhenti dapat menerima notifikasi penghentian yang dikirim oleh framework. Untuk menerima notifikasi, klien harus:
- Buat subclass class/antarmuka HIDL
hidl_death_recipient
(dalam kode C++, bukan di HIDL). - Ganti metode
serviceDied()
-nya. - Buat instance objek subclass
hidl_death_recipient
. - Panggil metode
linkToDeath()
pada layanan yang akan dipantau, dengan meneruskan objek antarmukaIDeathRecipient
. Perhatikan bahwa metode ini tidak mengambil kepemilikan penerima kematian atau proxy tempat metode ini dipanggil.
Contoh pseudocode (C++ dan Java serupa):
class IMyDeathReceiver : hidl_death_recipient { virtual void serviceDied(uint64_t cookie, wp<IBase>& service) override { log("RIP service %d!", cookie); // Cookie should be 42 } }; .... IMyDeathReceiver deathReceiver = new IMyDeathReceiver(); m_importantService->linkToDeath(deathReceiver, 42);
Penerima kematian yang sama dapat didaftarkan di beberapa layanan yang berbeda.
Transfer data
Data dapat dikirim ke layanan dengan memanggil metode yang ditentukan dalam antarmuka di
file .hal
. Ada dua jenis metode:
- Metode Pemblokiran menunggu hingga server menghasilkan hasil.
- Metode Oneway hanya mengirim data dalam satu arah dan tidak memblokir. Jika jumlah data yang sedang dikirim dalam panggilan RPC melebihi batas implementasi, panggilan tersebut dapat memblokir atau menampilkan indikasi error (perilaku belum ditentukan).
Metode yang tidak menampilkan nilai tetapi tidak dideklarasikan sebagai
oneway
masih memblokir.
Semua metode yang dideklarasikan di antarmuka HIDL dipanggil dalam satu arah, baik dari HAL maupun ke HAL. Antarmuka tidak menentukan arah panggilannya. Arsitektur yang memerlukan panggilan yang berasal dari HAL harus menyediakan dua (atau lebih) antarmuka dalam paket HAL dan menayangkan antarmuka yang sesuai dari setiap proses. Kata klien dan server digunakan sehubungan dengan arah panggilan antarmuka (yaitu HAL dapat menjadi server dari satu antarmuka dan klien dari antarmuka lain).
Callback
Kata callback merujuk pada dua konsep yang berbeda, yang dibedakan oleh callback sinkron dan callback asinkron.
Callback sinkron digunakan di beberapa metode HIDL yang menampilkan data. Metode HIDL yang menampilkan lebih dari satu nilai (atau menampilkan satu nilai jenis non-primitif) menampilkan hasilnya melalui fungsi callback. Jika hanya satu nilai yang ditampilkan dan merupakan jenis primitif, callback tidak digunakan dan nilai ditampilkan dari metode. Server mengimplementasikan metode HIDL dan klien mengimplementasikan callback.
Callback asinkron memungkinkan server antarmuka HIDL
memulai panggilan. Hal ini dilakukan dengan meneruskan instance antarmuka kedua
melalui antarmuka pertama. Klien antarmuka pertama harus bertindak sebagai
server antarmuka kedua. Server antarmuka pertama dapat memanggil metode pada
objek antarmuka kedua. Misalnya, implementasi HAL dapat mengirim informasi
secara asinkron kembali ke proses yang menggunakannya dengan memanggil metode pada
objek antarmuka yang dibuat dan ditayangkan oleh proses tersebut. Metode dalam antarmuka yang digunakan
untuk callback asinkron mungkin memblokir (dan mungkin menampilkan nilai ke pemanggil)
atau oneway
. Untuk contohnya, lihat "Callback asinkron" di
HIDL C++.
Untuk menyederhanakan kepemilikan memori, panggilan dan callback metode hanya mengambil
parameter in
dan tidak mendukung parameter out
atau
inout
.
Batas per transaksi
Batas per transaksi tidak diterapkan pada jumlah data yang dikirim dalam metode
dan callback HIDL. Namun, panggilan yang melebihi 4 KB per transaksi dianggap berlebihan. Jika hal ini terlihat, sebaiknya arsitektur antarmuka HIDL
yang diberikan dirancang ulang. Batasan lainnya adalah resource yang tersedia untuk infrastruktur
HIDL guna menangani beberapa transaksi secara bersamaan. Beberapa
transaksi dapat sedang berlangsung secara bersamaan karena beberapa thread atau
proses mengirim panggilan ke proses atau beberapa panggilan oneway
yang
tidak ditangani dengan cepat oleh proses penerima. Total ruang maksimum
yang tersedia untuk semua transaksi serentak adalah 1 MB secara default.
Dalam antarmuka yang dirancang dengan baik, melampaui batasan resource ini tidak boleh terjadi; jika terjadi, panggilan yang melampauinya dapat memblokir hingga resource tersedia atau menandakan error transpor. Setiap kejadian melampaui batas per transaksi atau melampaui resource implementasi HIDL dengan agregat transaksi yang sedang berlangsung akan dicatat dalam log untuk memfasilitasi proses debug.
Implementasi metode
HIDL menghasilkan file header yang mendeklarasikan jenis, metode, dan callback yang diperlukan dalam bahasa target (C++ atau Java). Prototipe metode dan callback yang ditentukan HIDL sama untuk kode klien dan server. Sistem HIDL menyediakan implementasi proxy metode di sisi pemanggil yang mengatur data untuk transpor IPC, dan kode stub di sisi pengakses yang meneruskan data ke implementasi developer metode.
Pemanggil fungsi (metode atau callback HIDL) memiliki kepemilikan struktur data yang diteruskan ke fungsi, dan mempertahankan kepemilikan setelah panggilan; dalam semua kasus, pemanggil tidak perlu mengosongkan atau melepaskan penyimpanan.
- Di C++, data mungkin hanya dapat dibaca (upaya menulis ke data tersebut dapat menyebabkan error segmentasi) dan valid selama durasi panggilan. Klien dapat melakukan deep copy data untuk menyebarkannya di luar panggilan.
- Di Java, kode menerima salinan lokal data (objek Java normal), yang dapat disimpan dan diubah atau diizinkan untuk di-garbage collection.
Transfer data non-RPC
HIDL memiliki dua cara untuk mentransfer data tanpa menggunakan panggilan RPC: memori bersama dan Antrean Pesan Cepat (FMQ), keduanya hanya didukung di C++.
- Memori bersama. Jenis HIDL bawaan
memory
digunakan untuk meneruskan objek yang mewakili memori bersama yang telah dialokasikan. Dapat digunakan dalam proses penerimaan untuk memetakan memori bersama. - Fast Message Queue (FMQ). HIDL menyediakan jenis antrean pesan
template yang menerapkan penerusan pesan tanpa tunggu. Mode ini tidak menggunakan kernel
atau penjadwal dalam mode passthrough atau binderized (komunikasi antar-perangkat tidak
memiliki properti ini). Biasanya, HAL menyiapkan akhir antreannya,
membuat objek yang dapat diteruskan melalui RPC melalui parameter jenis
HIDL bawaan
MQDescriptorSync
atauMQDescriptorUnsync
. Objek ini dapat digunakan oleh proses penerima untuk menyiapkan ujung lain antrean.- Antrean Sinkronisasi tidak diizinkan untuk meluap, dan hanya dapat memiliki satu pembaca.
- Antrean Unsync diizinkan untuk meluap, dan dapat memiliki banyak pembaca, yang masing-masing harus membaca data tepat waktu atau kehilangannya.
Untuk mengetahui detail selengkapnya tentang FMQ, lihat Antrean Pesan Cepat (FMQ).