HIDL veri bildirimleri, C++ standart düzen veri yapıları oluşturur. Bu yapılar, doğal hissettiren herhangi bir yere (yığına, dosyaya veya genel kapsama ya da yığına) yerleştirilebilir ve aynı şekilde derlenebilir. İstemci kodu, HIDL proxy kodunu çağırır ve const referansları ile ilkel türleri iletir. Bu sırada, stub ve proxy kodu, serileştirmenin ayrıntılarını gizler.
Not: Veri yapılarını açıkça serileştirmek veya serileştirmeyi kaldırmak için geliştirici tarafından yazılmış kodun hiçbir zaman kullanılması gerekmez.
Aşağıdaki tabloda HIDL ilkelleri C++ veri türleriyle eşleştirilmiştir:
HIDL türü | C++ Türü | Başlık/kitaplık |
---|---|---|
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 |
Aşağıdaki bölümlerde veri türleri daha ayrıntılı olarak açıklanmaktadır.
enum
HIDL'deki bir enum, C++'da enum olur. Örneğin:
enum Mode : uint8_t { WRITE = 1 << 0, READ = 1 << 1 }; enum SpecialMode : Mode { NONE = 0, COMPARE = 1 << 2 };
… şu hâle gelir:
enum class Mode : uint8_t { WRITE = 1, READ = 2 }; enum class SpecialMode : uint8_t { WRITE = 1, READ = 2, NONE = 0, COMPARE = 4 };
Android 10'dan itibaren, ::android::hardware::hidl_enum_range
kullanılarak bir enum üzerinde iterasyon yapılabilir. Bu aralık, ana enumeratörden son alt öğeye kadar HIDL kaynak kodunda göründüğü sıradaki her enumerasyonu içerir. Örneğin, bu kod WRITE
, READ
, NONE
ve COMPARE
değerlerini bu sırayla iteratif olarak işler. Yukarıdaki SpecialMode
değeri için:
template <typename T> using hidl_enum_range = ::android::hardware::hidl_enum_range<T> for (SpecialMode mode : hidl_enum_range<SpecialMode>) {...}
hidl_enum_range
, ters iteratörleri de uygular ve constexpr
bağlamlarında kullanılabilir. Bir değer bir sayımda birden çok kez görünüyorsa bu değer aralıkta da birden çok kez görünür.
bitfield<T>
bitfield<T>
(T
kullanıcı tanımlı bir enum ise), C++'ta bu enum'un temel türü olur. Yukarıdaki örnekte bitfield<Mode>
, uint8_t
olur.
vec<T>
hidl_vec<T>
sınıf şablonu, libhidlbase
'un bir parçasıdır ve herhangi bir HIDL türündeki bir vektörü rastgele bir boyutla iletmek için kullanılabilir. Karşılaştırılabilir sabit boyut kapsayıcı: hidl_array
. hidl_vec<T>
, hidl_vec::setToExternal()
işlevi kullanılarak T
türündeki harici bir veri arabelleğini işaret edecek şekilde de başlatılabilir.
vec<T>
kullanımı, yapıyı oluşturulan C++ başlığına uygun şekilde yayınlamaya/eklemeye ek olarak std::vector
ve çıplak T
işaretçileri arasında çeviri yapmak için bazı kolaylık işlevleri oluşturur. vec<T>
parametre olarak kullanılırsa bu parametreyi kullanan işlev, hem HIDL yapısını hem de ilgili parametre için bir std::vector<T>
türünü kabul edip iletmek üzere aşırı yüklenir (iki prototip oluşturulur).
dizi
Hidl'deki sabit diziler, libhidlbase
içindeki hidl_array
sınıfı tarafından temsil edilir. hidl_array<T, S1, S2, …,
SN>
, N boyutlu sabit boyutlu bir diziyi temsil ederT[S1][S2]…[SN]
.
dize
hidl_string
sınıfı (libhidlbase
'un bir parçasıdır), HIDL arayüzleri üzerinden dize aktarmak için kullanılabilir ve /system/libhidl/base/include/hidl/HidlSupport.h
içinde tanımlanır. Sınıftaki ilk depolama konumu, karakter arabelleğinin işaretçisidir.
hidl_string
, operator=
, örtülü yayınlama ve .c_str()
işlevini kullanarak std::string and char*
(C tarzı dize) ile arasında dönüşüm yapmayı bilir.
HIDL dize yapıları, aşağıdakiler için uygun kopyalama kurucularına ve atama operatörlerine sahiptir:
- HIDL dizesini bir
std::string
veya C dizesinden yükleyin. - HIDL dizelerinden yeni bir
std::string
oluşturun.
Ayrıca, HIDL dizelerinde dönüştürme kurucuları bulunur. Böylece, HIDL dizesi alan yöntemlerde C dizeleri (char *
) ve C++ dizeleri (std::string
) kullanılabilir.
struct
HIDL'de struct
yalnızca sabit boyutlu veri türleri içerebilir ve işlev içeremez. HIDL yapı tanımları, C++'da doğrudan standart düzene sahip struct
'lerle eşlenir. Bu sayede struct
'lerin tutarlı bir bellek düzenine sahip olması sağlanır. Bir yapı, ayrı değişken uzunlukta arabelleklere işaret eden handle
, string
ve vec<T>
gibi HIDL türleri içerebilir.
herkese açık kullanıcı adı
UYARI: Her tür adres (fiziksel cihaz adresleri dahil) hiçbir zaman yerel bir herkese açık kullanıcı adının parçası olmamalıdır. Bu bilgilerin süreçler arasında aktarılması tehlikelidir ve süreçleri saldırılara karşı savunmasız hale getirir. İşlemler arasında iletilen tüm değerler, bir işlemde ayrılan belleği aramak için kullanılmadan önce doğrulanmalıdır. Aksi takdirde, hatalı tutamaç kötü bellek erişimine veya bellek bozulmasına neden olabilir.
handle
türü, C++'da hidl_handle
yapısıyla temsil edilir. Bu yapı, const native_handle_t
nesnesine işaret eden bir işaretçi etrafında basit bir sarmalayıcıdır (Android'de uzun süredir mevcuttur).
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;
Varsayılan olarak hidl_handle
, sarmaladığı native_handle_t
işaretçisinin sahipliğini almaz. Yalnızca bir native_handle_t
işaretçisini hem 32 hem de 64 bit işlemlerde kullanılabilecek şekilde güvenli bir şekilde depolamak için vardır.
hidl_handle
'nin ekteki dosya tanımlayıcılarına sahip olduğu senaryolar şunlardır:
shouldOwn
parametresitrue
olarak ayarlanmışkensetTo(native_handle_t* handle, bool shouldOwn)
yönteminin çağrılmasından sonrahidl_handle
nesnesi, başka birhidl_handle
nesnesinden kopya oluşturma işlemiyle oluşturulduğundahidl_handle
nesnesi başka birhidl_handle
nesnesinden kopya atandığında
hidl_handle
, native_handle_t*
nesnelerine/native_handle_t*
nesnelerinden hem dolaylı hem de açık dönüşümler sağlar. HIDL'deki handle
türünün ana kullanımı, dosya tanımlayıcılarını HIDL arayüzleri üzerinden iletmektir. Bu nedenle, tek bir dosya tanımlayıcısı int
içermeyen bir native_handle_t
ve tek bir fd
ile temsil edilir. İstemci ve sunucu farklı bir işlemdeyse RPC uygulaması, her iki işlemin de aynı dosyada çalışabilmesini sağlamak için dosya tanımlayıcıyla otomatik olarak ilgilenir.
Bir işlem tarafından hidl_handle
içinde alınan dosya tanımlayıcısı söz konusu işlemde geçerli olsa da alıcı işlevin ötesinde devam etmez (işlev döndürüldüğünde kapatılır). Dosya tanımlayıcısına kalıcı erişim elde etmek isteyen bir işlemin, kapalı dosya tanımlayıcılarını dup()
veya hidl_handle
nesnesinin tamamını kopyalaması gerekir.
bellek
HIDL memory
türü, eşlenmemiş paylaşılan belleği temsil eden libhidlbase
'deki hidl_memory
sınıfına eşlenir. Bu, HIDL'de belleği paylaşmak için işlemler arasında aktarılması gereken nesnedir. Paylaşılan belleği kullanmak için:
IAllocator
örneği edinin (şu anda yalnızca "ashmem" örneği kullanılabilir) ve paylaşılan bellek ayırmak için kullanın.IAllocator::allocate()
, HIDL RPC üzerinden iletilebilecek velibhidlmemory
'ninmapMemory
işlevi kullanılarak bir işlemle eşlenebilecek birhidl_memory
nesnesi döndürür.mapMemory
, belleğe erişmek için kullanılabilecek birsp<IMemory>
nesnesine referans döndürür. (IMemory
veIAllocator
,android.hidl.memory@1.0
içinde tanımlanır.)
Bellek ayırmak için IAllocator
örneği kullanılabilir:
#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 }));
Bellekteki gerçek değişiklikler, mem
'ı oluşturan taraftaki veya HIDL RPC üzerinden alan taraftaki bir IMemory
nesnesi aracılığıyla yapılmalıdır.
// 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();
arayüz
Arayüzler nesne olarak iletilebilir. Arayüz kelimesi, android.hidl.base@1.0::IBase
türü için söz dizimi şekeri olarak kullanılabilir. Ayrıca, mevcut arayüz ve içe aktarılan tüm arayüzler bir tür olarak tanımlanır.
Arayüzleri barındıran değişkenler güçlü işaretçiler olmalıdır:
sp<IName>
. Arayüz parametreleri alan HIDL işlevleri, ham işaretçileri güçlü işaretçilere dönüştürerek sezgisel olmayan davranışlara neden olur (işaretçi beklenmedik bir şekilde temizlenebilir). Sorun yaşamamak için HIDL arayüzlerini her zaman sp<>
olarak saklayın.