Android 8 mendesain ulang Android OS untuk menentukan antarmuka yang jelas antara
platform Android yang tidak bergantung pada perangkat dan kode khusus perangkat dan vendor.
Android sudah menentukan banyak antarmuka tersebut dalam bentuk antarmuka HAL,
yang ditentukan sebagai header C di hardware/libhardware
. HIDL menggantikan
antarmuka HAL ini dengan antarmuka berversi stabil, yang dapat berupa antarmuka HIDL sisi klien dan
sisi server di C++ (dijelaskan di bawah) atau
Java.
Halaman di bagian ini menjelaskan implementasi C++ antarmuka HIDL,
termasuk detail tentang file yang dibuat secara otomatis dari file .hal
HIDL oleh compiler hidl-gen
, cara file ini dikemas, dan
cara mengintegrasikan file ini dengan kode C++ yang menggunakannya.
Implementasi klien dan server
Antarmuka HIDL memiliki implementasi klien dan server:
- Klien antarmuka HIDL adalah kode yang menggunakan antarmuka dengan memanggil metode di dalamnya.
- Server adalah implementasi antarmuka HIDL yang menerima panggilan dari klien dan menampilkan hasil (jika diperlukan).
Dalam transisi dari HAL libhardware
ke HAL HIDL, implementasi HAL
menjadi server dan proses yang memanggil HAL menjadi
klien. Implementasi default dapat menayangkan HAL passthrough dan
binderized, serta dapat berubah dari waktu ke waktu:
Gambar 1. Progres pengembangan untuk HAL lama.
Membuat klien HAL
Mulai dengan menyertakan library HAL dalam makefile:
- Buat:
LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
- Soong:
shared_libs: [ …, android.hardware.nfc@1.0 ]
Selanjutnya, sertakan file header HAL:
#include <android/hardware/nfc/1.0/IFoo.h> … // in code: sp<IFoo> client = IFoo::getService(); client->doThing();
Membuat server HAL
Untuk membuat implementasi HAL, Anda harus memiliki file .hal
yang mewakili HAL dan telah membuat file makefile untuk HAL menggunakan
-Lmakefile
atau -Landroidbp
di hidl-gen
(./hardware/interfaces/update-makefiles.sh
melakukannya untuk file HAL
internal dan merupakan referensi yang baik). Saat mentransfer HAL dari
libhardware
, Anda dapat melakukan banyak pekerjaan ini dengan mudah menggunakan c2hal.
Untuk membuat file yang diperlukan guna menerapkan HAL:
PACKAGE=android.hardware.nfc@1.0 LOC=hardware/interfaces/nfc/1.0/default/ m -j hidl-gen hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE
Agar HAL berfungsi dalam mode passthrough, Anda harus memiliki
fungsi HIDL_FETCH_IModuleName
yang berada di
/(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl(OPTIONAL_IDENTIFIER).so
dengan OPTIONAL_IDENTIFIER adalah string yang mengidentifikasi implementasi
passthrough. Persyaratan mode passthrough dipenuhi secara otomatis oleh
perintah di atas, yang juga membuat target android.hardware.nfc@1.0-impl
, tetapi ekstensi apa pun dapat digunakan. Misalnya,
android.hardware.nfc@1.0-impl-foo
menggunakan -foo
untuk
membedakan dirinya.
Jika HAL adalah versi minor atau ekstensi HAL
lain, HAL dasar harus digunakan untuk memberi nama biner ini. Misalnya,
implementasi android.hardware.graphics.mapper@2.1
harus
masih dalam biner yang disebut
android.hardware.graphics.mapper@2.0-impl(OPTIONAL_IDENTIFIER)
.
Biasanya, OPTIONAL_IDENTIFIER di sini akan menyertakan versi HAL
yang sebenarnya. Dengan memberi nama biner seperti ini, klien 2.0 dapat mengambilnya secara langsung,
dan klien 2.1 dapat meng-upcast implementasi.
Selanjutnya, isi stub dengan fungsi dan siapkan daemon. Contoh kode daemon (mendukung passthrough):
#include <hidl/LegacySupport.h> int main(int /* argc */, char* /* argv */ []) { return defaultPassthroughServiceImplementation<INfc>("nfc"); }
defaultPassthroughServiceImplementation
memanggil
dlopen()
untuk library -impl
yang disediakan dan menyediakannya sebagai
layanan binderized. Contoh kode daemon (untuk layanan binderized murni):
int main(int /* argc */, char* /* argv */ []) { // This function must be called before you join to ensure the proper // number of threads are created. The threadpool never exceeds // size one because of this call. ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/); sp<INfc> nfc = new Nfc(); const status_t status = nfc->registerAsService(); if (status != ::android::OK) { return 1; // or handle error } // Adds this thread to the threadpool, resulting in one total // thread in the threadpool. We could also do other things, but // would have to specify 'false' to willJoin in configureRpcThreadpool. ::android::hardware::joinRpcThreadpool(); return 1; // joinRpcThreadpool should never return }
Daemon ini biasanya berada di $PACKAGE + "-service-suffix"
(misalnya, android.hardware.nfc@1.0-service
), tetapi dapat berada di mana saja.
Sepolicy untuk class HAL
tertentu adalah atribut hal_<module>
(misalnya,
hal_nfc)
. Atribut ini harus diterapkan ke daemon yang menjalankan
HAL tertentu (jika proses yang sama menayangkan beberapa HAL, beberapa atribut
dapat diterapkan ke HAL tersebut).