Bahasa definisi antarmuka HAL atau HIDL adalah bahasa {i>interface description <i}(IDL) yang antarmuka antara HAL dan para penggunanya. HIDL memungkinkan penentuan jenis dan panggilan metode, yang dikumpulkan ke dalam antarmuka dan paket. Secara luas, HIDL adalah sistem untuk berkomunikasi antar codebase yang dapat dikompilasi secara independen.
HIDL dimaksudkan untuk digunakan untuk komunikasi antarproses (IPC). HAL yang dibuat dengan HDL yang disebut HAL terbinderisasi di mana mereka dapat berkomunikasi dengan lapisan arsitektur lain menggunakan binder panggilan komunikasi antarproses (IPC). HAL terbiner berjalan dalam proses terpisah dari klien yang menggunakannya. Sebagai library yang harus ditautkan ke proses, passthrough mode juga tersedia (tidak didukung di Java).
HIDL menentukan struktur data dan tanda tangan metode, yang diatur dalam antarmuka (mirip dengan class) yang dikumpulkan ke dalam paket. {i>Syntax <i}HIDL terlihat familier bagi C++ dan Programmer Java, tetapi dengan serangkaian kata kunci. HIDL juga menggunakan anotasi bergaya Java.
Terminologi
Bagian ini menggunakan istilah terkait HIDL berikut:
di-binderized | Menunjukkan bahwa HIDL digunakan untuk panggilan prosedur jarak jauh antar-proses, diterapkan melalui mekanisme mirip Binder. Lihat juga passthrough. |
---|---|
callback, asinkron | Antarmuka yang disajikan oleh pengguna HAL, diteruskan ke HAL (menggunakan metode HIDL), dan yang dipanggil oleh HAL untuk mengembalikan data kapan saja. |
callback, sinkron | Menampilkan data dari implementasi metode HIDL server ke klien. Tidak digunakan untuk metode yang menampilkan nilai primitif tunggal atau kosong. |
klien | Proses yang memanggil metode antarmuka tertentu. Kerangka kerja HAL atau Android proses mungkin menjadi klien dari satu antarmuka dan server dari antarmuka yang lain. Lihat juga passthrough. |
memperluas | Menunjukkan antarmuka yang menambahkan metode dan/atau jenis ke antarmuka lain. Satu antarmuka hanya dapat memperluas satu antarmuka lainnya. Dapat digunakan untuk anak di bawah umur kenaikan versi dalam nama paket yang sama atau untuk paket baru (mis. ekstensi) untuk membangun paket yang lebih lama. |
membuat | Menunjukkan metode antarmuka yang mengembalikan nilai ke klien. Untuk mengembalikan satu nilai non-primitif, atau lebih dari satu nilai, fungsi callback sinkron akan dibuat. |
antarmuka | Kumpulan metode dan jenis. Diterjemahkan ke dalam class dalam C++ atau Java. Semua metode dalam antarmuka dipanggil ke arah yang sama: proses klien memanggil metode yang diimplementasikan oleh proses server. |
sekali jalan | Bila diterapkan ke metode HIDL, mengindikasikan bahwa metode tidak mengembalikan nilai dan tidak memblokir. |
paket | Kumpulan antarmuka dan tipe data yang menggunakan satu versi. |
passthrough | Mode HIDL yang servernya adalah library bersama, dlopen ed
oleh klien. Dalam mode {i>passthrough<i}, klien dan server
adalah proses yang sama tetapi
codebase terpisah. Digunakan hanya untuk menghadirkan codebase lama ke model HIDL.
Lihat juga Terikat. |
server | Proses yang mengimplementasikan metode antarmuka. Lihat juga passthrough. |
transportasi | Infrastruktur HIDL yang memindahkan data antara server dan klien. |
version | Versi paket. Terdiri dari dua bilangan bulat, besar dan kecil. Anak di Bawah Umur penambahan versi dapat menambahkan (tetapi tidak mengubah) jenis dan metode. |
Desain HIDL
Tujuan HIDL adalah agar framework Android dapat diganti tanpa harus
membangun kembali HAL. HAL dibangun oleh vendor atau pembuat SOC dan dimasukkan ke dalam
Partisi /vendor
di perangkat, yang mengaktifkan framework Android secara mandiri
, untuk diganti dengan OTA tanpa
mengompilasi ulang HAL.
Desain HIDL menyeimbangkan beberapa hal berikut:
- Interoperabilitas. Membuat antarmuka dengan kemampuan interoperabilitas yang andal proses yang dapat dikompilasi dengan berbagai arsitektur, toolchain, dan konfigurasi build. Antarmuka HIDL memiliki beberapa versi dan tidak dapat diubah setelah dipublikasikan.
- Efisiensi. HIDL mencoba meminimalkan jumlah salinan operasional bisnis. Data yang didefinisikan HIDL dikirim ke kode C++ dalam tata letak standar C++ struktur data yang dapat digunakan tanpa membongkar. HIDL juga menyediakan dan, karena RPC pada dasarnya agak lambat, HIDL mendukung dua cara untuk mentransfer data tanpa menggunakan panggilan RPC: memori bersama dan Antrean Pesan (FMQ).
- Intuitif. HIDL menghindari masalah rumit kepemilikan memori dengan
hanya menggunakan parameter
in
untuk RPC (lihat Android Interface Definition Language (AIDL)); nilai-nilai yang tidak bisa diwujudkan secara efisien yang ditampilkan dari metode akan ditampilkan melalui fungsi callback. Tidak ada data yang diteruskan ke HIDL untuk mentransfer atau menerima data dari HIDL akan mengubah kepemilikan data—kepemilikan akan selalu tetap mengikuti fungsi pemanggil. Data perlu hanya bertahan selama durasi fungsi yang dipanggil dan dapat dihancurkan segera setelah fungsi yang dipanggil kembali.
Menggunakan mode passthrough
Untuk memperbarui perangkat yang menjalankan versi Android yang lebih lama ke Android O, Anda dapat menggabungkan HAL konvensional (dan lama) dalam antarmuka HIDL baru yang melayani HAL dalam mode binderized dan same-process (passthrough). Penggabungan ini adalah transparan untuk HAL dan kerangka kerja Android.
Mode passthrough hanya tersedia untuk klien dan implementasi C++. Perangkat yang menjalankan versi Android yang lebih lama tidak memiliki HAL yang ditulis dalam Java, jadi Java HAL secara inheren dibinder.
File header passthrough
Saat file .hal
dikompilasi, hidl-gen
akan menghasilkan
file header passthrough tambahan BsFoo.h
selain header
digunakan untuk komunikasi binder; {i>header<i} ini mendefinisikan fungsi untuk
dlopen
Saat HAL passthrough berjalan dengan
proses yang sama di mana
metode tersebut dipanggil. Dalam kebanyakan kasus, metode passthrough dipanggil
panggilan fungsi (thread yang sama). Metode oneway
berjalan di threadnya sendiri
karena tidak dimaksudkan untuk menunggu
HAL memprosesnya (ini berarti setiap HAL
yang menggunakan metode oneway
dalam mode passthrough harus aman untuk thread).
Dengan IFoo.hal
, BsFoo.h
menggabungkan HIDL yang dihasilkan
metode untuk menyediakan fitur tambahan (seperti membuat oneway
transaksi berjalan di thread lain). File ini mirip dengan
BpFoo.h
, tetapi alih-alih meneruskan panggilan IPC menggunakan binder,
fungsi yang diinginkan akan
dipanggil secara langsung. Implementasi HAL pada masa mendatang
dapat menyediakan beberapa implementasi, seperti FooFast HAL dan
HAL Foo Akurat. Dalam kasus tersebut, file untuk
setiap implementasi tambahan akan
dibuat (misalnya, PTFooFast.cpp
dan
PTFooAccurate.cpp
).
Membuat HAL passthrough
Anda bisa mem-binder implementasi HAL yang mendukung mode passthrough. Mengingat
Antarmuka HAL a.b.c.d@M.N::IFoo
, dua paket dibuat:
a.b.c.d@M.N::IFoo-impl
. Berisi implementasi HAL dan mengekspos fungsiIFoo* HIDL_FETCH_IFoo(const char* name)
. Aktif perangkat lama, paket ini di-dlopen
dan implementasinya adalah dibuat instance-nya menggunakanHIDL_FETCH_IFoo
. Anda dapat membuat kode dasar menggunakanhidl-gen
dan-Lc++-impl
, serta-Landroidbp-impl
.a.b.c.d@M.N::IFoo-service
. Membuka HAL passthrough dan mendaftarkan dirinya sebagai layanan binderized, yang memungkinkan implementasi HAL yang sama untuk digunakan sebagai {i> passthrough<i} dan {i>binderized<i}.
Dengan jenis IFoo
, Anda dapat memanggil sp<IFoo>
IFoo::getService(string name, bool getStub)
untuk mendapatkan akses ke instance
dari IFoo
. Jika getStub
benar, getService
mencoba membuka HAL hanya
dalam mode {i>passthrough<i}. Jika getStub
adalah
false, getService
mencoba menemukan layanan binder; kalau itu
gagal, maka ia mencoba
menemukan layanan {i>passthrough<i}. getStub
parameter tidak boleh digunakan kecuali dalam
defaultPassthroughServiceImplementation
. (Perangkat diluncurkan dengan
Android O adalah perangkat yang sepenuhnya di-binder, sehingga membuka layanan dalam mode passthrough
tidak diizinkan.)
Tata bahasa HIDL
Secara desain, bahasa HIDL mirip dengan C (tetapi tidak menggunakan C
praprosesor). Semua tanda baca yang tidak dijelaskan di bawah ini (selain penggunaan yang jelas
dari =
dan |
) adalah bagian dari tata bahasa.
Catatan: Untuk detail tentang gaya kode HIDL, lihat Panduan Gaya Kode.
/** */
menunjukkan komentar dokumentasi. Hal ini dapat diterapkan hanya untuk deklarasi nilai jenis, metode, kolom, dan enum./* */
menunjukkan komentar multibaris.//
menunjukkan komentar hingga akhir baris. Selain dari//
, baris baru sama dengan spasi kosong lainnya.- Pada contoh tata bahasa di bawah, teks dari
//
hingga akhir baris bukan bagian dari tata bahasa tetapi merupakan komentar pada tata bahasa. [empty]
berarti istilah boleh kosong.?
yang mengikuti literal atau istilah berarti opsional....
menunjukkan urutan yang berisi nol atau beberapa item dengan memisahkan tanda baca seperti yang ditunjukkan. Tidak ada argumen variadik dalam HIDL.- Koma memisahkan elemen urut.
- Titik koma menghentikan setiap elemen, termasuk elemen terakhir.
- HURUF BESAR adalah nonterminal.
italics
adalah kelompok token sepertiinteger
atauidentifier
(standar C aturan penguraian).constexpr
adalah ekspresi konstanta gaya C (seperti1 + 1
dan1L << 3
).import_name
adalah nama paket atau antarmuka, yang memenuhi syarat sebagaimana dijelaskan dalam HIDL Pembuatan versi.- Huruf kecil
words
adalah token literal.
Contoh:
ROOT = PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... } // not for types.hal | PACKAGE IMPORTS ITEM ITEM... // only for types.hal; no method definitions ITEM = ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?; | safe_union identifier { UFIELD; UFIELD; ...}; | struct identifier { SFIELD; SFIELD; ...}; // Note - no forward declarations | union identifier { UFIELD; UFIELD; ...}; | enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar | typedef TYPE identifier; VERSION = integer.integer; PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION; PREAMBLE = interface identifier EXTENDS EXTENDS = <empty> | extends import_name // must be interface, not package GENERATES = generates (FIELD, FIELD ...) // allows the Binder interface to be used as a type // (similar to typedef'ing the final identifier) IMPORTS = [empty] | IMPORTS import import_name; TYPE = uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t | float | double | bool | string | identifier // must be defined as a typedef, struct, union, enum or import // including those defined later in the file | memory | pointer | vec<TYPE> | bitfield<TYPE> // TYPE is user-defined enum | fmq_sync<TYPE> | fmq_unsync<TYPE> | TYPE[SIZE] FIELD = TYPE identifier UFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...}; | struct identifier { FIELD; FIELD; ...}; | union identifier { FIELD; FIELD; ...}; | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SIZE = // Must be greater than zero constexpr ANNOTATIONS = [empty] | ANNOTATIONS ANNOTATION ANNOTATION = | @identifier | @identifier(VALUE) | @identifier(ANNO_ENTRY, ANNO_ENTRY ...) ANNO_ENTRY = identifier=VALUE VALUE = "any text including \" and other escapes" | constexpr | {VALUE, VALUE ...} // only in annotations ENUM_ENTRY = identifier | identifier = constexpr