Veri türleri

Bu bölümde HIDL veri türleri açıklanmaktadır. Uygulama ayrıntıları için bkz. HIDL C++ (C++ için uygulamaları) veya HIDL Java (Java uygulamaları için).

C++ ile benzerlikler şunlardır:

  • structs C++ söz dizimini kullanır; unions desteği C++ söz dizimi varsayılan olarak. Her ikisinin de adı belirtilmelidir; anonim struct ve birleşimler desteklenmez.
  • Typedef'lere HIDL'de izin verilir (C++'ta olduğu gibi).
  • C++ stili yorumlara izin verilir ve bunlar, oluşturulan başlık dosyasına kopyalanır.

Java ile benzerlikler şunlardır:

  • HIDL her dosya için android.hardware. Oluşturulan C++ ad alanı ::android::hardware::…
  • Dosyanın tüm tanımları Java stili bir interface sarmalayıcı.
  • HIDL dizi bildirimleri C++ stilini değil, Java stilini kullanır. Örnek:
    struct Point {
        int32_t x;
        int32_t y;
    };
    Point[3] triangle;   // sized array
    
    .
  • Yorumlar, javadoc biçimine benzer.

Veri temsili

Şunlardan oluşan bir struct veya union: Standart-Düzen (düz veri türleri gereksinimlerinin bir alt kümesi) tutarlı bir belleğe sahiptir oluşturulan C++ kodunda açık hizalama özellikleri ile zorunlu kılınan düzen struct ve union üye.

Temel HIDL türleri, enum ve bitfield türler (her zaman temel türlerden türetilir), standart C++ türleriyle eşlenir. Örneğin, şuradan std::uint32_t cstdint.

Java imzasız türleri desteklemediğinden, imzasız HIDL türleri karşılık gelen imzalı Java türünü belirtmelidir. Yapılar, Java sınıflarıyla eşlenir; arrays, Java dizileriyle eşlenir; birlikler şu anda desteklenmemektedir yardımcı oldu. Dizeler dahili olarak UTF8 olarak depolanır. Java, yalnızca UTF16 dizeleri varsa, Java uygulamasına veya Java uygulamasından gönderilen dize değerleri tekrar çeviride aynı olmayabilir, çünkü bu, karakter kümelerindeki pratiğe dökebilirsiniz.

C++'ta IPC üzerinden alınan veriler const olarak işaretlenmiş ve şurada: işlev çağrısı süresince devam eden salt okunur bellek. Veri alınan IPC üzerinden alınanlar Java nesnelerine zaten kopyalanmıştır, dolayısıyla ek kopyalama olmadan saklanabilir (ve değiştirilebilir).

Ek Açıklamalar

Tür bildirimlerine Java stili ek açıklamalar eklenebilir. Ek açıklamalar HIDL derleyicisinin Tedarikçi Test Paketi (VTS) arka ucu tarafından ayrıştırıldı, ancak hiçbiri bu ayrıştırılan ek açıklamalar, HIDL derleyici tarafından anlaşılır. Bunun yerine ayrıştırılmış VTS ek açıklamaları, VTS Derleyici (VTSC) tarafından işlenir.

Ek açıklamalarda Java söz dizimi kullanılır: @annotation veya @annotation(value) veya @annotation(id=value, id=value…) Burada değer sabit bir ifade, dize veya değerler listesi olabilir. {} içinde, Java'da olduğu gibi. Aynı ada sahip birden çok ek açıklama aynı öğeye eklenebilir.

Bildirimleri yönlendir

HIDL'de struct'lar yönlendirme bildirilmeyebilir ve bu da kullanıcı tanımlı kendine referans veren veri türlerinin kullanılması imkansız (örneğin, bağlı bir listeyi açıklayamazsınız veya HIDL'deki bir ağaç). Mevcut (Android 8.x öncesi) HAL'lerin çoğunda sınırlı kullanım veri yapısının yeniden düzenlenmesiyle kaldırılabilecek yönlendirme bildirimleri beyanları.

Bu kısıtlama, veri yapılarının basit bir sorguyla değere göre kopyalanmasına olanak tanır. birden fazla kez oluşabilecek işaretçi değerlerini izlemek yerine derin kopya referans bir veri yapısında kullanır. Aynı veri iki kez aktarılırsa örneğin, iki yöntem parametresi veya vec<T> ile iki ayrı kopya üretilir ve teslim edilir.

İç içe yerleştirilmiş beyanlar

HIDL, iç içe yerleştirilmiş bildirimleri istenilen sayıda düzeyde destekler (tek bir istisna olarak faaliyet gösterin). Örnek:

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> ve yalnızca bir seviye derinde (hayır vec<vec<IFoo>>) tıklayın.

Ham işaretçi söz dizimi

HIDL dilinde * kullanılmadığından ve C/C++ ham işaretçileri için tam esneklik. HIDL'nin işaretçiler ve diziler/vektörler için bkz. vec<T> şablonunu seçin.

Arayüzler

interface anahtar kelimesinin iki kullanımı vardır.

  • Bir .hal dosyasında arayüzün tanımını açar.
  • Yapı/birleştirme alanlarında, yöntem parametrelerinde, ve geri dönüyor. Genel bir arayüz olarak görüntülenir ve eş anlamlıdır android.hidl.base@1.0::IBase

Örneğin, IServiceManager aşağıdaki yöntemi kullanır:

get(string fqName, string name) generates (interface service);

Yöntem, bir arayüzü ada göre aramayı taahhüt eder. Aynı zamanda arayüzün android.hidl.base@1.0::IBase ile değiştirilmesiyle aynıdır.

Arayüzler yalnızca iki şekilde aktarılabilir: üst düzey parametreler olarak veya vec<IMyInterface> üyeleri. Şu grubun üyesi olamazlar: iç içe geçmiş vecs, struct, dizi veya birleşimler.

MQDescriptorSync ve MQDescriptorUnsync

MQDescriptorSync ve MQDescriptorUnsync türleri Senkronize edilmiş veya senkronize edilmemiş bir Hızlı Mesaj Sırası (FMQ) tanımlayıcısını iletme test edebilirsiniz. Ayrıntılar için bkz. HIDL C++ (FMQ'lar değil desteklenir).

bellek türü

memory türü, şurada eşlenmemiş paylaşılan belleği göstermek için kullanılır: HIDL. Yalnızca C++'ta desteklenir. Bu tür bir değer alma ucu, IMemory nesnesini başlatmak için kullanılır ve hafızayı eşler kullanışlı hale getirmektir. Ayrıntılar için bkz. HIDL C++.

Uyarı: Yapılandırılmış veriler paylaşılan konuma yerleştirildi Bellek kullanımının ömrü boyunca biçimi hiçbir zaman değişmeyen memory öğesini ileten arayüz sürümü. Aksi takdirde, HAL'ler önemli uyumluluk sorunlarına neden olabilir.

işaretçi türü

pointer türü, yalnızca HIDL dahili kullanımı içindir.

bitfield<T> şablon türü

T değerinin bir olduğu bitfield<T> kullanıcı tanımlı enum, değerin T içinde tanımlanan enum değerleri. Oluşturulan kodda bitfield<T>, temel T türü olarak görünüyor. Örneğin, örnek:

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 kullanılmasın? (u)int32_t/(u)int16_t/(u)int8_t/(u)int64_t? bitfield kullanılması okuyucuya ek HAL bilgileri sağlar. artık setFlags için Flag'in bit tabanlı VEYA değerini aldığını bilen kişiler (ör. , 16 ile setFlags çağrısının geçersiz olduğunu bilir). Yok: bitfield, bu bilgiler yalnızca belgeler aracılığıyla aktarılıyor. İçinde ek olarak, VTS, işaretlerin değerinin İşaretin bit tabanlı VEYA olup olmadığını kontrol edebilir.

Temel tür tutma yerleri

UYARI: Her tür adres (fiziksel adres dahil) cihaz adresleri) hiçbir zaman yerel bir herkese açık kullanıcı adının parçası olmamalıdır. Geçiyorum bilgiler tehlikelidir ve saldırılara açık hale getirir. İşlemler arasında iletilen tüm değerler, kullanılmadan önce doğrulanmalıdır. bir işlemde ayrılmış belleği aramak için kullanır. Aksi takdirde, hatalı herkese açık kullanıcı adları sorun olabilir.

HIDL semantiği, parametrelerin kopyalandığı anlamına gelen değere göre kopyadır. Büyük veri parçaları veya süreçler arasında paylaşılması gereken veriler (ör. senkronizasyon parmaklığı) kalıcı nesnelere: Paylaşılan bellek, gerçek dosyalar için ashmem veya dosya tanımlayıcısının arkasına gizlenebilecek diğer her şeyi belirtir. Bağlayıcı sürücüsü dosya tanımlayıcısını diğer işleme kopyalar.

yerel_herkese_tanımlı_t

Android, genel bir herkese açık kullanıcı adı kavramı olan native_handle_t'i destekler. libcutils içinde tanımlanmıştır.

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 herkese açık kullanıcı adı, iletilen tüm bilgi ve dosya tanımlayıcılarından oluşan bir koleksiyondur. değer belirliyor. Tek bir dosya açıklayıcısı, tek bir dosya tanımlayıcısı bulunur. Yerel herkese açık kullanıcı adlarını kullanarak herkese açık kullanıcı adları geçirme handle temel türüyle kapsüllemesi, yerel herkese açık kullanıcı adları doğrudan HIDL'ye dahil edilir.

native_handle_t değişken boyuta sahip olduğu için dahil edilemez inceleyebilirsiniz. Herkese açık kullanıcı adı alanı, bir işaretçiyi ayrı bir native_handle_t tahsis edildi.

Android'in önceki sürümlerinde, yerel herkese açık kullanıcı adları aynı şurada bulunan işlevler: libcutils olarak değiştirin. Android 8.0 ve sonraki sürümlerde bu işlevler artık android::hardware::hidl ad alanına sahip veya NDK'ya taşındı. İDL otomatik olarak oluşturulan kod, bu işlevleri otomatik olarak serileştirir ve seri durumdan çıkarır. kullanıcı tarafından yazılan kod olmadan.

Herkese açık kullanıcı adı ve dosya açıklayıcı sahipliği

Bir HIDL arayüz yöntemini çağırarak hidl_handle nesne (üst düzey veya bir bileşik türünün parçası), bu belgede yer alan dosya tanımlayıcılarının sahipliği aşağıdaki gibidir:

  • Arayan, bir hidl_handle nesnesini bağımsız değişkeni, native_handle_t sarmalar; arayan, bu dosyaları kapatmalıdır tanımlar.
  • hidl_handle döndürme işlemi (bir _cb işlevine geçirerek) nesnesinin native_handle_t içinde bulunan ve nesne; İşlem tamamlandığında, dosya tanımlayıcılarının kapatılması gerekir.
  • hidl_handle alan bir aktarımda native_handle_t içindeki dosya tanımlayıcılarının sahipliği bir nesne tarafından sarmalanır; alıcı, bu dosya tanımlayıcılarını işlem geri çağırması, ancak dosyayı kullanmak için yerel herkese açık kullanıcı adını klonlaması gerekir geri çağırmanın ötesine geçer. Aktarım otomatik olarak İşlem tamamlandığında dosya tanımlayıcılar için close().

HIDL Java'daki herkese açık kullanıcı adlarını desteklemez (Java, tümü).

Boyutlu diziler

HIDL struct'larındaki boyutlu dizilerin öğeleri struct'ta herhangi bir türde olabilir şunları içerebilir:

struct foo {
uint32_t[3] x; // array is contained in foo
};

Yaylı Çalgılar

Dizeler C++ ve Java'da farklı görünür, ancak temel aktarım depolama alanı türü C++ yapısıdır. Ayrıntılar için bkz. HIDL C++ Veri Türleri veya HIDL Java Veri Türleri.

Not: HIDL arayüzü (Java'dan Java'ya dahil), karakter kümesi dönüşümlerine neden oluyor koruyamayabilir.

vec<T> şablon türü

vec<T> şablonu, değişken boyutlu bir arabelleği temsil eder T örneklerini içeren.

T şunlardan biri olabilir:

  • Temel türler (ör. uint32_t)
  • Yaylı Çalgılar
  • Kullanıcı tanımlı enum'lar
  • Kullanıcı tanımlı struct'lar
  • Arayüzler veya interface anahtar kelimesi (vec<IFoo>, vec<interface> desteklenir yalnızca üst düzey parametre olarak)
  • Herkese açık kullanıcı adları
  • bitfield<U>
  • vec<U>; burada U burada, arayüz hariç (ör. vec<vec<IFoo>> desteklenmez)
  • U[] (U boyutlu dizisi), burada U bu listede arayüz hariçtir

Kullanıcı tanımlı türler

Bu bölümde, kullanıcı tanımlı türler açıklanmaktadır.

Sıralama

HIDL, anonim enum'ları desteklemez. Aksi takdirde HIDL'deki sıralamalar benzerdir C++11'e taşıma:

enum name : type { enumerator , enumerator = constexpr , …  }

Temel sıralama, HIDL'deki tam sayı türlerinden biri ile tanımlanır. Yanıt hayır ise: bir tamsayıya dayalı enum'un ilk numaralandırıcısı için değer belirtilir türünde, 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. Örnek:

// RED == 0
// BLUE == 4 (GREEN + 1)
enum Color : uint32_t { RED, GREEN = 3, BLUE }

Bir numaralandırma, önceden tanımlanmış bir numaralandırmadan da devralabilir. Hiçbir değer bir alt enum'un ilk numaralandırıcısı için belirtilir (bu örnekte FullSpectrumColor), varsayılan olarak son üst enum artı bir'in numaralandırıcısı. Örnek:

// ULTRAVIOLET == 5 (Color:BLUE + 1)
enum FullSpectrumColor : Color { ULTRAVIOLET }

Uyarı: Sıralama devralma işlemi geriye dönük olarak çalışır ortaya çıkarır. Alt sıralama değeri şu şekilde kullanılamaz: üst sıralama değeri. Bunun nedeni, bir alt sıralamanın üst öğesidir. Bununla birlikte, üst numaralandırma değeri alt numaralandırma değeri olarak güvenli bir şekilde kullanılabilir çünkü alt numaralandırma değerleri, tanımı gereği üst numaralandırma değerlerinin üst kümesidir. Arayüz tasarlarken bunu göz önünde bulundurun; çünkü bu, aynı metin üst numaralandırmalar, kullanır.

Sıralama değerleri, iki nokta üst üste söz dizimiyle belirtilir ( iç içe yerleştirilmiş türler). Söz dizimi Type:VALUE_NAME şeklindedir. Belirtilmesine gerek yok değere aynı enum türü veya alt türlerde başvuruluyorsa şunu yazın. Ö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 sıralamalarda Sabit ifadelerde kullanılabilecek len özelliği. MyEnum::len, bu sıralamadaki girişlerin toplam sayısıdır. Bu, toplam değer sayısından farklıdır. Toplam değer sayısı değerleri yinelenir.

Yapı

HIDL, anonim struct'ları desteklemez. Aksi takdirde, HIDL'deki struct'lar C ile benzer.

HIDL, tamamen içinde yer alan değişken uzunlukta veri yapılarını desteklemez bir struct'ı içerir. Bu, bazen C/C++ işlevindeki bir struct'ın son alanı (bazen [0]). HIDL vec<T> dinamik olarak boyutu temsil eder ayrı bir arabellekte depolanan verilerle diziler; bu tür örnekler struct içindeki vec<T> öğesinin bir örneğiyle.

Benzer şekilde, string, bir struct içinde yer alabilir (ilişkili tamponlar ayrıdır). Oluşturulan C++ öğelerinde HIDL örnekleri herkese açık kullanıcı adı türü, bir işaretçiyle gerçek yerel herkese açık kullanıcı adı için temel veri türünün örnekleri değişken uzunluktadır.

Union

HIDL anonim birlikleri desteklemez. Aksi takdirde sendikalar C ile benzerdir.

Birlikler düzeltme türleri (ör. işaretçiler, dosya tanımlayıcıları, bağlayıcı) içeremez nesneleri) ekleyin. Özel alan veya ilişkili türlere ihtiyaç duymazlar. memcpy() veya eşdeğeri kullanılarak kopyalanmaz. Sendika doğrudan başka veri yapılarının kullanımını içeren (veya başka veri yapıları kullanan) bağlayıcı ofsetleri (yani tutma veya bağlayıcı arayüzü başvuruları). Örnek:

union UnionType {
uint32_t a;
//  vec<uint32_t> r;  // Error: can't contain a vec<T>
uint8_t b;1
};
fun8(UnionType info); // Legal

Birleştirmeler, struct'ların içinde de bildirilebilir. Örnek:

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
  }