Layanan & Transfer Data

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

Layanan pendaftaran

Server antarmuka HIDL (objek yang mengimplementasikan antarmuka) dapat didaftarkan sebagai layanan bernama. Nama terdaftar 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 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. Ini secara otomatis dikaitkan dengan pendaftaran layanan dan dapat diambil melalui pemanggilan 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 oleh kode klien dibuat untuk antarmuka yang diberikan 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. Dengan demikian, IFooService versi 1.1 dan IFooService versi 2.2 keduanya dapat didaftarkan sebagai "foo_service" dan getService("foo_service") pada kedua antarmuka mendapatkan layanan terdaftar untuk antarmuka tersebut. Inilah sebabnya, dalam banyak kasus, tidak ada parameter nama yang perlu disediakan untuk pendaftaran atau penemuan (artinya nama "default").

Obyek 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 dalam manifes perangkat jika ada entri; dan jika metode transport tidak tersedia, nullptr dikembalikan.

Dalam beberapa kasus, mungkin perlu untuk segera melanjutkan bahkan tanpa mendapatkan layanan. Ini dapat terjadi (misalnya) ketika klien ingin mengelola pemberitahuan 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 pemberitahuan layanan. Menggunakan API ini tidak menghindari kondisi balapan di mana server mendaftarkan dirinya sendiri setelah klien memintanya dengan salah satu API tanpa percobaan ini.

Pemberitahuan kematian layanan

Klien yang ingin diberi tahu saat layanan mati dapat menerima pemberitahuan kematian yang disampaikan oleh framework. Untuk menerima pemberitahuan, klien harus:

  1. Subkelas kelas/antarmuka 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 kepemilikan penerima kematian atau proxy yang disebut.

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 pada beberapa layanan yang 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 satu arah mengirim data hanya dalam satu arah dan tidak memblokir. Jika jumlah data dalam penerbangan dalam panggilan RPC melebihi batas implementasi, panggilan 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 mana yang akan dipanggil. Arsitektur yang membutuhkan 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 panggilan antarmuka (yaitu HAL dapat menjadi server dari satu antarmuka dan klien dari antarmuka lain).

Panggilan balik

Kata callback mengacu pada dua konsep yang berbeda, dibedakan oleh synchronous callback dan asynchronous callback .

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 itu adalah tipe primitif, panggilan balik tidak digunakan dan nilai dikembalikan dari metode. Server mengimplementasikan metode HIDL dan klien mengimplementasikan callback.

Panggilan balik asinkron memungkinkan server antarmuka HIDL untuk memulai panggilan. Hal ini dilakukan dengan melewatkan sebuah instance dari antarmuka kedua melalui antarmuka pertama. Klien dari antarmuka pertama harus bertindak sebagai server yang 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 dilayani oleh proses itu. Metode dalam antarmuka yang digunakan untuk panggilan balik asinkron mungkin memblokir (dan dapat mengembalikan nilai ke pemanggil) atau oneway . Sebagai contoh, lihat "Panggilan balik asinkron" di HIDL C++ .

Untuk menyederhanakan kepemilikan memori, pemanggilan metode dan callback hanya in parameter dan tidak inout parameter out atau keluar.

Batas per transaksi

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

Dalam antarmuka yang dirancang dengan baik, tidak boleh terjadi melebihi batasan sumber daya ini; jika ya, panggilan yang melebihinya dapat memblokir hingga sumber daya tersedia atau menandakan kesalahan transportasi. Setiap kejadian melebihi batas per transaksi atau sumber daya implementasi HIDL yang meluap oleh transaksi dalam penerbangan agregat dicatat untuk memfasilitasi debugging.

Implementasi metode

HIDL menghasilkan file header yang menyatakan jenis, metode, dan panggilan balik 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 dari metode di sisi pemanggil yang mengatur data untuk transportasi IPC, dan kode rintisan di sisi panggilan 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 callee tidak perlu membebaskan atau melepaskan penyimpanan.

  • Di C++, data mungkin hanya-baca (usaha untuk menulisnya dapat menyebabkan kesalahan segmentasi) dan valid selama panggilan berlangsung. Klien dapat menyalin data secara mendalam untuk menyebarkannya di luar panggilan.
  • Di Java, kode menerima salinan data lokal (objek Java normal), yang mungkin disimpan dan dimodifikasi atau diizinkan untuk dikumpulkan.

Transfer data non-RPC

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

  • Memori bersama . memory tipe HIDL bawaan digunakan untuk melewatkan 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 berpola yang mengimplementasikan pengiriman pesan tanpa menunggu. Itu tidak menggunakan kernel atau penjadwal dalam mode passthrough atau binderized (komunikasi antar perangkat tidak akan memiliki properti ini). Biasanya, HAL menyiapkan akhir antriannya, membuat objek yang dapat diteruskan melalui RPC melalui parameter tipe MQDescriptorSync atau MQDescriptorUnsync . Objek ini dapat digunakan oleh proses penerima untuk mengatur ujung antrian yang lain.
    • Antrean sinkronisasi tidak boleh meluap, dan hanya dapat memiliki satu pembaca.
    • Antrian yang tidak sinkron dibiarkan meluap, dan dapat memiliki banyak pembaca, yang masing-masing harus membaca data tepat waktu atau kehilangannya.
    Tidak ada jenis yang diizinkan untuk mengalir (membaca dari antrian kosong akan gagal), dan setiap jenis hanya dapat memiliki satu penulis.

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