Bu bölümde HIDL veri türleri açıklanmaktadır. Uygulama ayrıntıları için bkz. HIDL C++ (C++ uygulamaları için) veya HIDL Java (Java uygulamaları için).
C++ ile benzerlikler şunları içerir:
-
structs
C++ sözdizimini kullanır;unions
varsayılan olarak C++ sözdizimini destekler. Her ikisinin de adlandırılması gerekir; anonim yapılar ve birleşimler desteklenmez. - HIDL'de tip tanımlarına izin verilir (C++'da olduğu gibi).
- C++ tarzı yorumlara izin verilir ve oluşturulan başlık dosyasına kopyalanır.
Java ile benzerlikler şunları içerir:
- HIDL, her dosya için
android.hardware.
. Oluşturulan C++ ad alanı::android::hardware::…
. - Dosyanın tüm tanımları Java tarzı bir
interface
sarmalayıcısında bulunur. - HIDL dizisi bildirimleri C++ stilini değil Java stilini izler. Örnek:
struct Point { int32_t x; int32_t y; }; Point[3] triangle; // sized array
- Yorumlar javadoc formatına benzer.
Temsili veri
Standart Düzen'den (düz eski veri türlerinin gereksinimlerinin bir alt kümesi) oluşan bir struct
veya union
, oluşturulan C++ kodunda struct
ve union
üyelerinde açık hizalama nitelikleriyle uygulanan tutarlı bir bellek düzenine sahiptir.
İlkel HIDL türlerinin yanı sıra enum
ve bitfield
türleri (her zaman ilkel türlerden türetilir), cstdint'ten std::uint32_t
gibi standart C++ türleriyle eşlenir.
Java imzasız türleri desteklemediğinden, imzasız HIDL türleri karşılık gelen imzalı Java türüyle eşlenir. Yapılar Java sınıflarıyla eşleşir; diziler Java dizileriyle eşleşir; birleşimler şu anda Java'da desteklenmemektedir. Dizeler dahili olarak UTF8 olarak saklanır. Java yalnızca UTF16 dizelerini desteklediğinden, bir Java uygulamasına gönderilen veya Java uygulamasından gönderilen dize değerleri çevrilir ve karakter kümeleri her zaman düzgün şekilde eşlenmediğinden yeniden çeviride aynı olmayabilir.
C++'da IPC üzerinden alınan veriler const
olarak işaretlenir ve yalnızca işlev çağrısı süresince kalıcı olan salt okunur bellekte bulunur. Java'da IPC üzerinden alınan veriler zaten Java nesnelerine kopyalanmıştır, dolayısıyla ek kopyalamaya gerek kalmadan saklanabilir (ve değiştirilebilir).
Ek açıklamalar
Tür bildirimlerine Java tarzı açıklamalar eklenebilir. Ek açıklamalar, HIDL derleyicisinin Satıcı Test Paketi (VTS) arka ucu tarafından ayrıştırılır, ancak bu tür ayrıştırılan ek açıklamaların hiçbiri aslında HIDL derleyicisi tarafından anlaşılmaz. Bunun yerine, ayrıştırılmış VTS ek açıklamaları VTS Derleyicisi (VTSC) tarafından işlenir.
Ek açıklamalar Java sözdizimini kullanır: @annotation
veya @annotation(value)
veya @annotation(id=value, id=value…)
burada değer, tıpkı aşağıdaki gibi, sabit bir ifade, bir dize veya {}
içindeki bir değerler listesi olabilir. Java. Aynı öğeye aynı adda birden fazla ek açıklama eklenebilir.
İleri beyanlar
HIDL'de yapılar ileri bildirimli olmayabilir, bu da kullanıcı tanımlı, kendine referanslı veri türlerini imkansız hale getirir (örneğin, HIDL'de bağlantılı bir listeyi veya bir ağacı tanımlayamazsınız). Mevcut (Android 8.x öncesi) HAL'lerin çoğu, ileri bildirimlerin sınırlı kullanımına sahiptir ve bu, veri yapısı bildirimlerinin yeniden düzenlenmesiyle kaldırılabilir.
Bu kısıtlama, kendine referanslı bir veri yapısında birden çok kez oluşabilecek işaretçi değerlerinin izini sürmek yerine, veri yapılarının basit bir derin kopya ile değere göre kopyalanmasına olanak tanır. Aynı veri iki yöntem parametresi veya aynı veriye işaret eden vec<T>
ile iki kez iletilirse, iki ayrı kopya oluşturulur ve teslim edilir.
İç içe bildirimler
HIDL, iç içe bildirimleri istenilen düzeyde destekler (aşağıda belirtilen bir istisna dışında). Örneğin:
interface IFoo { uint32_t[3][4][5][6] multidimArray; vec<vec<vec<int8_t>>> multidimVector; vec<bool[4]> arrayVec; struct foo { struct bar { uint32_t val; }; bar b; } struct baz { foo f; foo.bar fb; // HIDL uses dots to access nested type names } …
Bunun istisnası, arayüz türlerinin yalnızca vec<T>
içine ve yalnızca bir düzey derinliğe gömülebilmesidir ( vec<vec<IFoo>>
yok).
Ham işaretçi sözdizimi
HIDL dili * kullanmaz ve C/C++ ham işaretçilerinin tam esnekliğini desteklemez. HIDL'nin işaretçileri ve dizileri/vektörleri nasıl kapsüllediğine ilişkin ayrıntılar için bkz. vec<T> şablonu .
Arayüzler
interface
anahtar sözcüğünün iki kullanımı vardır.
- Bir .hal dosyasındaki arayüzün tanımını açar.
- Yapı/birlik alanlarında, yöntem parametrelerinde ve dönüşlerde özel bir tür olarak kullanılabilir. Genel bir arayüz ve
android.hidl.base@1.0::IBase
ile eşanlamlı olarak görülüyor.
Örneğin, IServiceManager
aşağıdaki yönteme sahiptir:
get(string fqName, string name) generates (interface service);
Yöntem, bazı arayüzleri ada göre aramayı vaat ediyor. Arayüzü android.hidl.base@1.0::IBase
ile değiştirmek de aynıdır.
Arayüzler yalnızca iki şekilde iletilebilir: üst düzey parametreler olarak veya bir vec<IMyInterface>
üyesi olarak. İç içe geçmiş vec'lerin, yapıların, dizilerin veya birliklerin üyesi olamazlar.
MQDescriptorSync ve MQDescriptorUnsync
MQDescriptorSync
ve MQDescriptorUnsync
türleri, bir HIDL arayüzü üzerinden senkronize edilmiş veya senkronize edilmemiş bir Hızlı Mesaj Kuyruğu (FMQ) tanımlayıcılarını iletir. Ayrıntılar için bkz. HIDL C++ (FMQ'lar Java'da desteklenmez).
bellek türü
memory
türü, HIDL'de eşlenmemiş paylaşılan belleği temsil etmek için kullanılır. Yalnızca C++'da desteklenir. Bu türden bir değer, alıcı tarafta bir IMemory
nesnesini başlatmak, belleği eşlemek ve kullanılabilir hale getirmek için kullanılabilir. Ayrıntılar için bkz. HIDL C++ .
Uyarı: Paylaşılan belleğe yerleştirilen yapılandırılmış veriler, memory
geçen arayüz sürümünün ömrü boyunca formatı asla değişmeyecek bir tür OLMALIDIR. Aksi takdirde HAL'ler ölümcül uyumluluk sorunları yaşayabilir.
işaretçi türü
pointer
türü yalnızca HIDL dahili kullanımı içindir.
bitfield<T> türü şablonu
T
kullanıcı tanımlı bir numaralandırma olduğu bitfield<T>
değerin T
içinde tanımlanan numaralandırma değerlerinin bit düzeyinde VEYA olduğunu gösterir. Oluşturulan kodda bitfield<T>
T'nin temel türü olarak görünür. Örneğin:
enum Flag : uint8_t { HAS_FOO = 1 << 0, HAS_BAR = 1 << 1, HAS_BAZ = 1 << 2 }; typedef bitfield<Flag> Flags; setFlags(Flags flags) generates (bool success);
Derleyici, Flags türünü uint8_t
ile aynı şekilde işler.
Neden (u)int8_t
/ (u)int16_t
/ (u)int32_t
/ (u)int64_t
kullanmıyorsunuz? bitfield
kullanılması, setFlags
Flag'in bit düzeyinde VEYA değerini aldığını artık bilen okuyucuya ek HAL bilgisi sağlar (yani setFlags
16 ile çağırmanın geçersiz olduğunu bilir). bitfield
olmadan bu bilgiler yalnızca dokümantasyon yoluyla aktarılır. Ek olarak VTS, bayrakların değerinin Bayrağın bit düzeyinde VEYA olup olmadığını gerçekten kontrol edebilir.
ilkel türü ele al
UYARI: Her türlü adres (fiziksel cihaz adresleri bile) hiçbir zaman yerel tanıtıcının parçası olmamalıdır. Bu bilgilerin süreçler arasında aktarılması tehlikelidir ve onları saldırıya açık hale getirir. İşlemler arasında iletilen herhangi bir değer, bir işlem içinde tahsis edilen belleği aramak için kullanılmadan önce doğrulanmalıdır. Aksi takdirde hatalı tanıtıcılar hatalı belleğe erişime veya belleğin bozulmasına neden olabilir.
HIDL semantiği değere göre kopyalanır, bu da parametrelerin kopyalandığı anlamına gelir. Büyük veri parçaları veya işlemler arasında paylaşılması gereken veriler (bir senkronizasyon çiti gibi), kalıcı nesnelere işaret eden dosya tanımlayıcılarının etrafından geçirilerek işlenir: paylaşılan bellek için ashmem
, gerçek dosyalar veya arkasına saklanabilecek başka herhangi bir şey. bir dosya tanımlayıcı. Ciltleyici sürücüsü, dosya tanımlayıcısını diğer işleme kopyalar.
native_handle_t
Android, libcutils
tanımlanan genel bir tanıtıcı kavramı olan native_handle_t
öğesini destekler.
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;
Yerel tanıtıcı, değere göre aktarılan bir int ve dosya tanımlayıcı koleksiyonudur. Tek bir dosya tanımlayıcı, ints olmadan ve tek bir dosya tanımlayıcıyla yerel bir tanıtıcıda saklanabilir. handle
temel türüyle kapsüllenmiş yerel tanıtıcıları kullanan tanıtıcıların geçirilmesi, yerel tanıtıcıların doğrudan HIDL'ye dahil edilmesini sağlar.
Bir native_handle_t
değişken boyuta sahip olduğundan doğrudan yapıya dahil edilemez. Bir tanıtıcı alanı, ayrı olarak tahsis edilmiş bir native_handle_t
için bir işaretçi oluşturur.
Android'in önceki sürümlerinde, libcutils'de bulunan aynı işlevler kullanılarak yerel tanıtıcılar oluşturuldu. Android 8.0 ve üzeri sürümlerde, bu işlevler artık android::hardware::hidl
ad alanına kopyalanmıştır veya NDK'ya taşınmıştır. HIDL otomatik olarak oluşturulan kod, bu işlevleri kullanıcı tarafından yazılan kodun katılımı olmadan otomatik olarak serileştirir ve seri durumdan çıkarır.
Tanıtıcı ve dosya tanımlayıcı sahipliği
Bir hidl_handle
nesnesini (üst düzey veya bileşik türün bir parçası) ileten (veya döndüren) bir HIDL arabirim yöntemini çağırdığınızda, içinde bulunan dosya tanımlayıcıların sahipliği aşağıdaki gibidir:
- Bağımsız değişken olarak bir
hidl_handle
nesnesini ileten çağıran , sardığınative_handle_t
dosyasında bulunan dosya tanımlayıcılarının sahipliğini korur; arayan kişinin bu dosya tanımlayıcılarla işi bittiğinde bunları kapatması gerekir. - Bir
hidl_handle
nesnesini döndüren süreç (bunu bir_cb
işlevine geçirerek), nesnenin sardığınative_handle_t
dosyasında bulunan dosya tanımlayıcılarının sahipliğini korur; işlem bu dosya tanımlayıcılarla tamamlandığında kapatılmalıdır. - Bir
hidl_handle
alan aktarım , nesne tarafından sarılmışnative_handle_t
içindeki dosya tanımlayıcılarının sahipliğine sahiptir; alıcı, işlem geri çağırma sırasında bu dosya tanımlayıcılarını olduğu gibi kullanabilir, ancak geri aramanın ötesinde dosya tanımlayıcılarını kullanmak için yerel tanıtıcıyı klonlaması gerekir. Aktarım, işlem tamamlandığında dosya tanımlayıcılarını otomatik olarakclose()
.
HIDL, Java'daki tanıtıcıları desteklemez (çünkü Java tanıtıcıları hiç desteklemez).
Boyutlandırılmış diziler
HIDL yapılarındaki boyutlu dizilerin öğeleri, bir yapının içerebileceği herhangi bir türde olabilir:
struct foo { uint32_t[3] x; // array is contained in foo };
Teller
Dizeler C++ ve Java'da farklı görünür, ancak temel aktarım depolama türü bir C++ yapısıdır. Ayrıntılar için bkz. HIDL C++ Veri Türleri veya HIDL Java Veri Türleri .
Not: Bir dizenin Java'ya veya Java'dan HIDL arabirimi (Java'dan Java'ya dahil) aracılığıyla iletilmesi, orijinal kodlamayı tam olarak koruyamayabilecek karakter kümesi dönüşümlerine neden olur.
vec<T> türü şablonu
vec<T>
şablonu, T
örneklerini içeren değişken boyutlu bir arabelleği temsil eder.
T
aşağıdakilerden biri olabilir:
- İlkel türler (örn. uint32_t)
- Teller
- Kullanıcı tanımlı numaralandırmalar
- Kullanıcı tanımlı yapılar
- Arayüzler veya
interface
anahtar sözcüğü (vec<IFoo>
,vec<interface>
yalnızca üst düzey bir parametre olarak desteklenir) - Kollar
- bit alanı<U>
- vec<U>, burada arayüz hariç U bu listede yer alır (örn.
vec<vec<IFoo>>
desteklenmez) - U[] (U'nun boyutlu dizisi), burada U, arayüz dışında bu listededir
Kullanıcı tanımlı türler
Bu bölümde kullanıcı tanımlı türler açıklanmaktadır.
Sıralama
HIDL anonim numaralandırmaları desteklemez. Aksi takdirde, HIDL'deki numaralandırmalar C++11'e benzer:
enum name : type { enumerator , enumerator = constexpr , … }
Bir temel numaralandırma, HIDL'deki tamsayı türlerinden birine göre tanımlanır. Tamsayı türüne dayalı bir numaralandırmanın ilk numaralandırıcısı için değer belirtilmezse, değer varsayılan olarak 0 olur. Daha sonraki bir numaralandırıcı için değer belirtilmezse, değer varsayılan olarak önceki değer artı bir olur. Örneğin:
// RED == 0 // BLUE == 4 (GREEN + 1) enum Color : uint32_t { RED, GREEN = 3, BLUE }
Bir numaralandırma ayrıca önceden tanımlanmış bir numaralandırmadan da miras alabilir. Bir alt numaralandırmanın ilk numaralandırıcısı için bir değer belirtilmemişse (bu durumda FullSpectrumColor
), varsayılan olarak üst numaralandırmanın son numaralandırıcısının değeri artı bir olur. Örneğin:
// ULTRAVIOLET == 5 (Color:BLUE + 1) enum FullSpectrumColor : Color { ULTRAVIOLET }
Uyarı: Enum mirası, diğer birçok miras türünden geriye doğru çalışır. Bir alt numaralandırma değeri, üst numaralandırma değeri olarak kullanılamaz. Bunun nedeni, bir alt numaralandırmanın ebeveynden daha fazla değer içermesidir. Bununla birlikte, alt numaralandırma değerleri tanım gereği üst numaralandırma değerlerinin bir üst kümesi olduğundan, bir üst numaralandırma değeri güvenli bir şekilde alt numaralandırma değeri olarak kullanılabilir. Arayüzleri tasarlarken bunu aklınızda bulundurun; çünkü bu, ana numaralandırmalara atıfta bulunan türlerin, arayüzünüzün daha sonraki yinelemelerinde alt numaralandırmalara başvuramayacağı anlamına gelir.
Numaralandırmaların değerleri iki nokta üst üste sözdizimi ile anılır (iç içe türler olarak nokta sözdizimi değil). Söz dizimi Type:VALUE_NAME
. Değere aynı numaralandırma türünde veya alt türlerde başvuruluyorsa türü belirtmenize gerek yoktur. Örnek:
enum Grayscale : uint32_t { BLACK = 0, WHITE = BLACK + 1 }; enum Color : Grayscale { RED = WHITE + 1 }; enum Unrelated : uint32_t { FOO = Color:RED + 1 };
Android 10'dan itibaren numaralandırmalar, sabit ifadelerde kullanılabilen bir len
özelliğine sahiptir. MyEnum::len
bu numaralandırmadaki toplam giriş sayısıdır. Bu, toplam değer sayısından farklıdır ve değerler kopyalandığında daha küçük olabilir.
Yapı
HIDL anonim yapıları desteklemez. Aksi halde HIDL'deki yapılar C'ye çok benzer.
HIDL, tamamen bir yapı içinde yer alan değişken uzunluktaki veri yapılarını desteklemez. Bu, bazen C/C++'da bir yapının son alanı olarak kullanılan (bazen [0]
boyutuyla görülen) belirsiz uzunluklu diziyi içerir. HIDL vec<T>
verileri ayrı bir arabellekte depolanan dinamik olarak boyutlandırılmış dizileri temsil eder; bu tür örnekler struct
içindeki vec<T>
örneğiyle temsil edilir.
Benzer şekilde, string
bir struct
içinde yer alabilir (ilişkili arabellekler ayrıdır). Oluşturulan C++'da, HIDL tanıtıcı türünün örnekleri, temeldeki veri türünün örnekleri değişken uzunlukta olduğundan, gerçek yerel tanıtıcıya yönelik bir işaretçi aracılığıyla temsil edilir.
Birlik
HIDL anonim birleşmeleri desteklemez. Aksi takdirde sendikalar C'ye benzer.
Birleşimler düzeltme türleri (işaretçiler, dosya tanımlayıcılar, ciltleyici nesneler vb.) içeremez. Özel alanlara veya ilgili türlere ihtiyaç duymazlar ve memcpy()
veya eşdeğeri aracılığıyla kolayca kopyalanırlar. Bir birleşim, ciltleyici ofsetlerinin ayarlanmasını gerektiren herhangi bir şeyi (yani tanıtıcı veya ciltleyici arayüzü referansları) doğrudan içeremez (veya diğer veri yapıları aracılığıyla içeremez). Örneğin:
union UnionType { uint32_t a; // vec<uint32_t> r; // Error: can't contain a vec<T> uint8_t b;1 }; fun8(UnionType info); // Legal
Birlikler yapıların içinde de bildirilebilir. Örneğin:
struct MyStruct { union MyUnion { uint32_t a; uint8_t b; }; // declares type but not member union MyUnion2 { uint32_t a; uint8_t b; } data; // declares type but not member }