HIDL

Bahasa definisi antarmuka HAL atau HIDL adalah bahasa deskripsi antarmuka ({i>interface description language<i}, IDL) untuk 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 gaya 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. Sebuah 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 merupakan library bersama, dlopened 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 operations. 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.

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 fungsi IFoo* HIDL_FETCH_IFoo(const char* name). Aktif perangkat lama, paket ini di-dlopen dan implementasinya adalah dibuat instance-nya menggunakan HIDL_FETCH_IFoo. Anda dapat membuat kode dasar menggunakan hidl-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 seperti integer atau identifier (standar C aturan penguraian).
  • constexpr adalah ekspresi konstanta gaya C (seperti 1 + 1 dan 1L << 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