C++ HIDL

Android 8 merancang ulang Android OS untuk mendefinisikan antarmuka yang jelas antara platform Android yang tidak bergantung pada perangkat, serta kode khusus perangkat dan vendor. Android sudah mendefinisikan banyak antarmuka seperti itu dalam bentuk antarmuka HAL, ditentukan sebagai header C di hardware/libhardware. HIDL menggantikan Antarmuka HAL dengan antarmuka berversi stabil, yang bisa berupa antarmuka HIDL sisi server di C++ (dijelaskan di bawah) atau Java telah selesai.

Halaman di bagian ini menjelaskan implementasi C++ antarmuka HIDL, termasuk detail tentang file yang dibuat secara otomatis dari .hal HIDL oleh compiler hidl-gen, cara file ini dikemas, dan cara mengintegrasikan file-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 pengguna dengan memanggil metode di dalamnya.
  • Server adalah implementasi antarmuka HIDL yang menerima panggilan dari klien dan mengembalikan hasilnya (jika perlu).

Dalam transisi dari libhardware HAL ke HIDL HAL, menjadi server dan proses yang memanggil HAL menjadi klien. Implementasi default dapat berfungsi sebagai passthrough dan binderized HAL, dan dapat berubah dari waktu ke waktu:

Gambar 1. Perkembangan pengembangan untuk HAL lama.

Membuat klien HAL

Mulailah dengan menyertakan library HAL di makefile:

  • Membuat: LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
  • Soong: shared_libs: [ …, android.hardware.nfc@1.0 ]

Selanjutnya, sertakan file {i>header<i} 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 Anda dan telah membuat {i> makefile<i} untuk HAL Anda menggunakan -Lmakefile atau -Landroidbp di hidl-gen (./hardware/interfaces/update-makefiles.sh melakukan hal ini untuk file HAL dan merupakan referensi yang baik). Saat mentransfer melalui HAL dari libhardware, Anda dapat melakukan banyak hal ini dengan mudah menggunakan c2hal.

Untuk membuat file yang diperlukan guna mengimplementasikan HAL Anda:

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 bekerja dalam mode {i>passthrough<i}, 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 passthrough terlepas dari implementasi layanan. Persyaratan mode passthrough dipenuhi secara otomatis oleh di atas, yang juga membuat error android.hardware.nfc@1.0-impl target, tetapi ekstensi apa pun dapat digunakan. Misalnya android.hardware.nfc@1.0-impl-foo menggunakan -foo untuk membedakan dirinya sendiri.

Jika HAL adalah versi minor atau perluasan dari versi lain HAL, HAL dasar harus digunakan untuk menamai biner ini. Contohnya, Penerapan 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 mencakup HAL yang sebenarnya . Dengan menamai biner seperti ini, klien 2,0 dapat mengambilnya secara langsung, dan 2.1 klien dapat mengganggu implementasinya.

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 panggilan 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" (untuk misalnya, android.hardware.nfc@1.0-service), tetapi bisa juga di mana saja. Sepolicy untuk kebijakan kelas HAL adalah atribut hal_<module> (misalnya, hal_nfc). Atribut ini harus diterapkan ke daemon yang menjalankan HAL tertentu (jika proses yang sama melayani beberapa HAL, beberapa atribut yang dapat diterapkan).