Deklarasi data HIDL menghasilkan struktur data tata letak standar C++. Ini struktur dapat ditempatkan di mana saja yang terasa alami (di atas tumpukan, di dalam file atau global, atau pada heap) dan dapat disusun dengan cara yang sama. Klien kode memanggil kode {i>proxy<i} HIDL yang meneruskan referensi konstanta dan tipe primitif, sedangkan stub dan kode {i>proxy<i} menyembunyikan detail serialisasi.
Catatan: Tidak ada kode yang ditulis developer yang diperlukan untuk melakukan serialisasi atau deserialisasi struktur data secara eksplisit.
Tabel di bawah memetakan primitif HIDL ke jenis data C++:
Jenis HiDL | Jenis C++ | Header/library |
---|---|---|
enum |
enum class |
|
uint8_t..uint64_t |
uint8_t..uint64_t |
<stdint.h> |
int8_t..int64_t |
int8_t..int64_t |
<stdint.h> |
float |
float |
|
double |
double |
|
vec<T> |
hidl_vec<T> |
libhidlbase |
T[S1][S2]...[SN] |
T[S1][S2]...[SN] |
|
string |
hidl_string |
libhidlbase |
handle |
hidl_handle |
libhidlbase |
safe_union |
(custom) struct |
|
struct |
struct |
|
union |
union |
|
fmq_sync |
MQDescriptorSync |
libhidlbase |
fmq_unsync |
MQDescriptorUnsync |
libhidlbase |
Bagian di bawah ini menjelaskan jenis data secara lebih mendetail.
enum
Enum dalam HIDL menjadi enum dalam C++. Contoh:
enum Mode : uint8_t { WRITE = 1 << 0, READ = 1 << 1 }; enum SpecialMode : Mode { NONE = 0, COMPARE = 1 << 2 };
... menjadi:
enum class Mode : uint8_t { WRITE = 1, READ = 2 }; enum class SpecialMode : uint8_t { WRITE = 1, READ = 2, NONE = 0, COMPARE = 4 };
Mulai Android 10, enum dapat diiterasi
berlebihan menggunakan ::android::hardware::hidl_enum_range
. Rentang ini
mencakup setiap enumerator dalam urutan yang muncul dalam kode sumber HIDL, mulai
dari enum induk hingga
turunan terakhir. Misalnya, kode ini mengiterasi
di atas WRITE
, READ
, NONE
, dan
COMPARE
dalam urutan tersebut. Dengan SpecialMode
di atas:
template <typename T> using hidl_enum_range = ::android::hardware::hidl_enum_range<T> for (SpecialMode mode : hidl_enum_range<SpecialMode>) {...}
hidl_enum_range
juga mengimplementasikan iterator terbalik dan dapat
digunakan dalam konteks constexpr
. Jika sebuah nilai muncul dalam enumerasi
beberapa kali, nilai akan muncul
dalam rentang beberapa kali.
bitfield<T>
bitfield<T>
(dengan T
adalah enum yang ditentukan pengguna)
menjadi jenis yang mendasari enum tersebut di C++. Dalam contoh di atas,
bitfield<Mode>
menjadi uint8_t
.
vec<T>
Template class hidl_vec<T>
adalah bagian dari
libhidlbase
dan dapat digunakan untuk meneruskan vektor jenis HIDL apa pun dengan
ukuran arbitrer. Penampung ukuran tetap yang sebanding adalah
hidl_array
. hidl_vec<T>
juga dapat berupa
diinisialisasi untuk mengarah ke buffer data eksternal jenis T
, menggunakan
fungsi hidl_vec::setToExternal()
.
Selain memunculkan/menyisipkan struct dengan tepat dalam
header C++, penggunaan vec<T>
menghasilkan beberapa kemudahan
fungsi untuk menerjemahkan ke/dari std::vector
dan T
tanpa www
pointer. Jika vec<T>
digunakan sebagai parameter, fungsi tersebut
menggunakan kelebihan beban (dua prototipe dibuat) untuk menerima dan
teruskan struct HIDL dan jenis std::vector<T>
untuk
.
array
Array konstanta dalam hidl diwakili oleh class hidl_array
dalam libhidlbase
. hidl_array<T, S1, S2, …,
SN>
mewakili array ukuran tetap N dimensi
T[S1][S2]…[SN]
.
string
Class hidl_string
(bagian dari libhidlbase
) dapat berupa
digunakan untuk meneruskan {i>string<i} melalui antarmuka HIDL dan didefinisikan dalam
/system/libhidl/base/include/hidl/HidlSupport.h
. Penyimpanan pertama
lokasi di class merupakan pointer ke buffer karakternya.
hidl_string
tahu cara mengonversi ke dan dari
std::string and char*
(string gaya C) menggunakan
operator=
, transmisi implisit, dan fungsi .c_str()
.
Struct string HIDL memiliki konstruktor dan penetapan salinan yang sesuai
operator ke:
- Muat string HIDL dari string
std::string
atau C. - Buat
std::string
baru dari string HIDL.
Selain itu, {i>string<i} HIDL memiliki konstruktor konversi sehingga {i>string<i} C
String (char *
) dan C++ (std::string
) dapat digunakan di
metode yang mengambil string HIDL.
struktur
struct
di HIDL hanya dapat berisi jenis data berukuran tetap dan tidak
fungsi-fungsi lainnya. Definisi struct HIDL dipetakan langsung ke tata letak standar
struct
di C++, yang memastikan bahwa struct
memiliki
dan tata letak memori yang konsisten. Sebuah struct dapat mencakup jenis HIDL, termasuk
handle
, string
, dan vec<T>
, yang
menunjuk ke buffer panjang variabel yang terpisah.
handle
PERINGATAN: Segala jenis alamat (bahkan alamat fisik alamat perangkat) tidak boleh menjadi bagian dari nama sebutan channel native. Meneruskan ini informasi antar proses berbahaya dan membuat mereka rentan terhadap serangan. Setiap nilai yang diteruskan di antara proses harus divalidasi sebelum digunakan untuk memori yang dialokasikan dalam suatu proses. Jika tidak, penanganan yang buruk dapat menyebabkan masalah akses memori atau kerusakan memori.
Jenis handle
direpresentasikan oleh hidl_handle
di C++, yang merupakan wrapper sederhana di sekitar pointer ke
Objek const native_handle_t
(ini telah ada di Android selama
lama).
typedef struct native_handle { int version; /* sizeof(native_handle_t) */ int numFds; /* number of file descriptors at &data[0] */ int numInts; /* number of ints at &data[numFds] */ int data[0]; /* numFds + numInts ints */ } native_handle_t;
Secara default, hidl_handle
tidak mengambil alih kepemilikan
dari pointer native_handle_t
yang digabungkannya. Program ini hanya ada untuk melindungi
menyimpan pointer ke native_handle_t
sedemikian rupa sehingga dapat digunakan di
proses 32-bit dan 64-bit.
Skenario saat hidl_handle
memiliki file yang tertutup
deskripsi tersebut meliputi:
- Mengikuti panggilan ke metode
setTo(native_handle_t* handle, bool shouldOwn)
dengan parametershouldOwn
yang disetel ketrue
- Saat objek
hidl_handle
dibuat dengan konstruksi teks dari objekhidl_handle
lain - Saat objek
hidl_handle
disalin dan ditetapkan dari objek lainhidl_handle
objek
hidl_handle
memberikan konversi implisit dan eksplisit
dari objek native_handle_t*
. Penggunaan utama untuk
Jenis handle
dalam HIDL adalah meneruskan deskriptor file melalui HIDL
antarmuka. Oleh karena itu, satu deskriptor file diwakili oleh
native_handle_t
tanpa int
dan satu
fd
. Jika klien dan server hidup dalam
proses yang berbeda, PPK
implementasi secara otomatis menangani deskriptor file untuk
kedua proses dapat beroperasi
pada file yang sama.
Meskipun deskriptor file diterima dalam hidl_handle
oleh
valid dalam proses itu, dan tidak
berlangsung di luar proses penerimaan
(tutup saat fungsi kembali). Sebuah proses yang ingin
mempertahankan akses persisten ke deskriptor file harus dup()
deskriptor file yang tertutup, atau menyalin seluruh objek hidl_handle
.
memori
Jenis memory
HIDL dipetakan ke class hidl_memory
di libhidlbase
, yang mewakili memori bersama yang tidak dipetakan. Ini adalah
objek yang harus diteruskan di antara proses untuk berbagi memori di HIDL. Kepada
menggunakan memori bersama:
- Dapatkan instance
IAllocator
(saat ini hanya instance "ashmem" tersedia) dan menggunakannya untuk mengalokasikan memori bersama. IAllocator::allocate()
menampilkanhidl_memory
yang dapat diteruskan melalui HIDL RPC dan dipetakan ke dalam proses menggunakan FungsimapMemory
libhidlmemory
.mapMemory
menampilkan referensi ke Objeksp<IMemory>
yang dapat digunakan untuk mengakses memori. (IMemory
danIAllocator
ditentukan diandroid.hidl.memory@1.0
.)
Instance IAllocator
dapat digunakan untuk mengalokasikan memori:
#include <android/hidl/allocator/1.0/IAllocator.h> #include <android/hidl/memory/1.0/IMemory.h> #include <hidlmemory/mapping.h> using ::android::hidl::allocator::V1_0::IAllocator; using ::android::hidl::memory::V1_0::IMemory; using ::android::hardware::hidl_memory; .... sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); ashmemAllocator->allocate(2048, [&](bool success, const hidl_memory& mem) { if (!success) { /* error */ } // now you can use the hidl_memory object 'mem' or pass it around }));
Perubahan aktual pada memori harus dilakukan melalui IMemory
di sisi yang membuat mem
atau di sisi yang
menerimanya melalui HIDL RPC.
// Same includes as above sp<IMemory> memory = mapMemory(mem); void* data = memory->getPointer(); memory->update(); // update memory however you wish after calling update and before calling commit data[0] = 42; memory->commit(); // … memory->update(); // the same memory can be updated multiple times // … memory->commit();
antarmuka
Antarmuka dapat diteruskan sebagai objek. Kata antarmuka dapat digunakan
sebagai sugar sintaksis untuk jenis android.hidl.base@1.0::IBase
;
sebagai tambahan, antarmuka saat ini dan antarmuka
yang diimpor akan ditentukan
sebagai suatu jenis.
Variabel yang menyimpan Antarmuka harus berupa pointer yang kuat:
sp<IName>
. Fungsi HIDL yang mengambil parameter antarmuka
mengonversi pointer mentah menjadi pointer yang kuat, menyebabkan perilaku yang tidak intuitif
(pointer dapat terhapus secara tidak terduga). Untuk menghindari masalah, selalu simpan HIDL
antarmuka sebagai sp<>
.