Layanan dan transfer data

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:

  1. Buat subclass class/antarmuka HIDL hidl_death_recipient (dalam kode C++, bukan di HIDL).
  2. Ganti metode serviceDied()-nya.
  3. Buat instance objek subclass 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 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 atau MQDescriptorUnsync. 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.
    Kedua jenis tersebut tidak diizinkan untuk underflow (membaca dari antrean kosong akan gagal), dan setiap jenis hanya dapat memiliki satu penulis.

Untuk mengetahui detail selengkapnya tentang FMQ, lihat Antrean Pesan Cepat (FMQ).