Layanan & Transfer data

Bagian ini menjelaskan cara mendaftar dan menemukan layanan serta cara mengirim data ke layanan dengan memanggil metode yang ditentukan dalam antarmuka dalam file .hal .

Mendaftarkan layanan

Server antarmuka HIDL (objek yang mengimplementasikan antarmuka) dapat didaftarkan sebagai layanan bernama. Nama yang didaftarkan tidak perlu terkait dengan antarmuka atau nama paket. Jika tidak ada nama yang ditentukan, nama "default" digunakan; ini harus digunakan untuk HAL yang tidak perlu mendaftarkan dua implementasi antarmuka yang sama. Misalnya, panggilan C++ untuk registrasi 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. Ini secara otomatis dikaitkan dengan pendaftaran layanan dan dapat diambil melalui panggilan metode ( android::hardware::IInterface::getInterfaceVersion() ) pada setiap antarmuka HIDL. Objek server tidak perlu didaftarkan dan dapat diteruskan melalui parameter metode HIDL ke proses lain yang akan membuat pemanggilan metode HIDL ke server.

Menemukan layanan

Permintaan berdasarkan kode klien dibuat untuk antarmuka tertentu berdasarkan nama dan versi, memanggil getService pada kelas 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. Jadi, IFooService versi 1.1 dan IFooService versi 2.2 keduanya dapat didaftarkan sebagai "foo_service" dan getService("foo_service") di salah satu antarmuka mendapatkan layanan terdaftar untuk antarmuka tersebut. Inilah sebabnya, dalam banyak kasus, tidak ada parameter nama yang perlu diberikan untuk registrasi atau penemuan (artinya nama "default").

Objek Antarmuka Vendor juga berperan dalam metode transportasi antarmuka yang dikembalikan. Untuk antarmuka IFoo dalam paket android.hardware.foo@1.0 , antarmuka yang dikembalikan oleh IFoo::getService selalu menggunakan metode transport yang dideklarasikan untuk android.hardware.foo di manifes perangkat jika entri tersebut ada; dan jika metode transportasi tidak tersedia, nullptr dikembalikan.

Dalam beberapa kasus, mungkin perlu untuk segera melanjutkan bahkan tanpa mendapatkan layanan tersebut. Hal ini dapat terjadi (misalnya) ketika klien ingin mengelola notifikasi layanan itu sendiri atau dalam program diagnostik (seperti atrace ) yang perlu mendapatkan semua layanan hw 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. Penggunaan API ini tidak menghindari kondisi balapan di mana server mendaftarkan dirinya sendiri setelah klien memintanya dengan salah satu API tanpa percobaan ulang ini.

Pemberitahuan kematian layanan

Klien yang ingin diberi tahu ketika layanan mati dapat menerima pemberitahuan kematian yang dikirimkan oleh kerangka kerja. Untuk menerima notifikasi, klien harus:

  1. Subkelas kelas/antarmuka HIDL hidl_death_recipient (dalam kode C++, bukan dalam HIDL).
  2. Ganti metode serviceDied() -nya.
  3. Buat instance objek dari subkelas hidl_death_recipient .
  4. Panggil metode linkToDeath() pada layanan yang akan dipantau, dengan meneruskan objek antarmuka IDeathRecipient . Perhatikan bahwa metode ini tidak mengambil alih kepemilikan penerima kematian atau kuasa yang memanggilnya.

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 mungkin terdaftar pada beberapa layanan berbeda.

Transfer data

Data dapat dikirim ke layanan dengan memanggil metode yang ditentukan dalam antarmuka dalam file .hal . Ada dua macam metode:

  • Metode pemblokiran menunggu hingga server memberikan hasil.
  • Metode oneway mengirimkan data hanya dalam satu arah dan tidak memblokir. Jika jumlah data dalam penerbangan dalam panggilan RPC melebihi batas implementasi, panggilan tersebut dapat memblokir atau mengembalikan indikasi kesalahan (perilaku belum ditentukan).

Metode yang tidak mengembalikan nilai tetapi tidak dideklarasikan sebagai oneway masih memblokir.

Semua metode yang dideklarasikan dalam antarmuka HIDL dipanggil dalam satu arah, baik dari HAL atau ke HAL. Antarmuka tidak menentukan arah pemanggilannya. Arsitektur yang memerlukan panggilan untuk berasal dari HAL harus menyediakan dua (atau lebih) antarmuka dalam paket HAL dan melayani antarmuka yang sesuai dari setiap proses. Kata klien dan server digunakan sehubungan dengan arah pemanggilan antarmuka (yaitu HAL dapat menjadi server dari satu antarmuka dan klien dari antarmuka lain).

Panggilan balik

Kata panggilan balik mengacu pada dua konsep berbeda, dibedakan dengan panggilan balik sinkron dan panggilan balik asinkron .

Callback sinkron digunakan dalam beberapa metode HIDL yang mengembalikan data. Metode HIDL yang mengembalikan lebih dari satu nilai (atau mengembalikan satu nilai tipe non-primitif) mengembalikan hasilnya melalui fungsi panggilan balik. Jika hanya satu nilai yang dikembalikan dan merupakan tipe primitif, panggilan balik tidak digunakan dan nilai dikembalikan dari metode. Server mengimplementasikan metode HIDL dan klien mengimplementasikan callback.

Callback asinkron memungkinkan server antarmuka HIDL memulai panggilan. Hal ini dilakukan dengan melewatkan sebuah instance dari 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 mengirimkan informasi kembali secara asinkron ke proses yang menggunakannya dengan memanggil metode pada objek antarmuka yang dibuat dan dilayani oleh proses tersebut. Metode dalam antarmuka yang digunakan untuk panggilan balik asinkron mungkin memblokir (dan mungkin mengembalikan nilai ke pemanggil) atau oneway . Misalnya, lihat "Panggilan balik asinkron" di HIDL C++ .

Untuk menyederhanakan kepemilikan memori, pemanggilan metode dan panggilan balik hanya in parameter dan tidak mendukung parameter out atau inout .

Batas per transaksi

Batasan per transaksi tidak dikenakan pada jumlah data yang dikirim dalam metode dan panggilan balik HIDL. Namun panggilan yang melebihi 4KB per transaksi dianggap berlebihan. Jika ini terlihat, disarankan untuk merancang ulang antarmuka HIDL yang diberikan. Keterbatasan lainnya adalah sumber daya yang tersedia pada infrastruktur HIDL untuk menangani beberapa transaksi secara bersamaan. Beberapa transaksi dapat dilakukan secara bersamaan karena beberapa thread atau proses mengirimkan panggilan ke suatu proses atau beberapa panggilan oneway yang tidak ditangani dengan cepat oleh proses penerimaan. Total ruang maksimum yang tersedia untuk semua transaksi bersamaan adalah 1MB secara default.

Dalam antarmuka yang dirancang dengan baik, melebihi batasan sumber daya ini tidak boleh terjadi; jika ya, panggilan yang melampauinya mungkin akan diblokir hingga sumber daya tersedia atau menandakan kesalahan transportasi. Setiap kejadian melebihi batas per transaksi atau meluapnya sumber daya implementasi HIDL oleh agregat transaksi dalam penerbangan dicatat untuk memfasilitasi proses debug.

Implementasi metode

HIDL menghasilkan file header yang mendeklarasikan tipe, metode, dan callback yang diperlukan dalam bahasa target (C++ atau Java). Prototipe metode dan panggilan balik yang ditentukan HIDL adalah sama untuk kode klien dan server. Sistem HIDL menyediakan implementasi proxy dari metode di sisi pemanggil yang mengatur data untuk transportasi IPC, dan kode rintisan di sisi callee yang meneruskan data ke implementasi metode pengembang.

Pemanggil suatu fungsi (metode HIDL atau panggilan balik) memiliki kepemilikan atas struktur data yang diteruskan ke fungsi tersebut, dan mempertahankan kepemilikan setelah panggilan; dalam semua kasus, pihak yang dipanggil tidak perlu mengosongkan atau melepaskan penyimpanan.

  • Dalam C++, data mungkin bersifat read-only (usaha untuk menulis ke data tersebut dapat menyebabkan kesalahan segmentasi) dan valid selama durasi panggilan. Klien dapat menyalin data secara mendalam untuk menyebarkannya di luar panggilan.
  • Di Java, kode menerima salinan data lokal (objek Java normal), yang dapat disimpan dan dimodifikasi atau dibiarkan dikumpulkan dari sampah.

Transfer data non-RPC

HIDL memiliki dua cara untuk mentransfer data tanpa menggunakan panggilan RPC: memori bersama dan Fast Message Queue (FMQ), keduanya hanya didukung di C++.

  • Berbagi memori . memory tipe HIDL bawaan digunakan untuk meneruskan objek yang mewakili memori bersama yang telah dialokasikan. Dapat digunakan dalam proses penerimaan untuk memetakan memori bersama.
  • Antrian Pesan Cepat (FMQ) . HIDL menyediakan tipe antrian pesan templat yang mengimplementasikan penyampaian pesan tanpa menunggu. Itu tidak menggunakan kernel atau penjadwal dalam mode passthrough atau binder (komunikasi antar perangkat tidak akan memiliki properti ini). Biasanya, HAL mengatur akhir antriannya, membuat objek yang dapat dilewatkan melalui RPC melalui parameter tipe HIDL bawaan MQDescriptorSync atau MQDescriptorUnsync . Objek ini dapat digunakan oleh proses penerima untuk mengatur ujung antrian lainnya.
    • Antrean sinkronisasi tidak boleh meluap, dan hanya dapat memiliki satu pembaca.
    • Antrean yang tidak disinkronkan dibiarkan meluap, dan dapat memiliki banyak pembaca, yang masing-masing harus membaca data tepat waktu atau data akan hilang.
    Tidak ada tipe yang diperbolehkan untuk mengalami underflow (pembacaan dari antrian kosong akan gagal), dan setiap tipe hanya dapat memiliki satu penulis.

Untuk detail lebih lanjut tentang FMQ, lihat Antrean Pesan Cepat (FMQ) .