HAL arayüz tanımlama dili veya HIDL, HAL ile kullanıcıları arasındaki arayüzü belirtmek için kullanılan bir arayüz tanımlama dilidir (IDL). HIDL, arayüzler ve paketler halinde toplanan türlerin ve yöntem çağrılarının belirlenmesine olanak tanır. Daha genel anlamda HIDL, bağımsız olarak derlenebilen kod tabanları arasında iletişim kurmaya yönelik bir sistemdir. Android 10'dan itibaren HIDL kullanımdan kaldırıldı ve Android, AIDL'yi her yerde kullanacak şekilde taşınıyor.
HIDL'nin işlemler arası iletişim (IPC) için kullanılması amaçlanmıştır. HDL ile oluşturulan HAL'lere, bağlayıcı işlemler arası iletişim (IPC) çağrılarını kullanarak diğer mimari katmanlarla iletişim kurabilmeleri nedeniyle bağlayıcı hale getirilmiş HAL'ler denir. Bağlayıcı hale getirilmiş HAL'ler, onları kullanan istemciden ayrı bir işlemde çalışır. Bir işleme bağlanması gereken kitaplıklar için bir geçiş modu da mevcuttur (Java'da desteklenmez).
HIDL, paketler halinde toplanan arayüzlerde (bir sınıfa benzer) düzenlenen veri yapılarını ve yöntem imzalarını belirtir. HIDL'in sözdizimi C++ ve Java programcılarına tanıdık gelir, ancak anahtar sözcükler farklıdır. HIDL ayrıca Java tarzı ek açıklamalar kullanır.
Terminoloji
Bu bölümde HIDL ile ilgili aşağıdaki terimler kullanılmaktadır:
ciltlenmiş | HIDL'nin, Binder benzeri bir mekanizma üzerinden uygulanan işlemler arasındaki uzaktan prosedür çağrıları için kullanıldığını belirtir. Ayrıca bkz . geçiş . |
---|---|
geri arama, eşzamansız | Bir HAL kullanıcısı tarafından sunulan, HAL'e iletilen (HIDL yöntemi kullanılarak) ve herhangi bir zamanda veri döndürmek için HAL tarafından çağrılan arayüz. |
geri arama, senkronize | Bir sunucunun HIDL yöntemi uygulamasından istemciye veri döndürür. Geçersiz veya tek bir temel değer döndüren yöntemler için kullanılmaz. |
müşteri | Belirli bir arayüzün yöntemlerini çağıran süreç. Bir HAL veya Android çerçeve işlemi, bir arayüzün istemcisi ve diğerinin sunucusu olabilir. Ayrıca bkz . geçiş . |
uzanır | Başka bir arayüze yöntemler ve/veya türler ekleyen bir arayüzü belirtir. Bir arayüz yalnızca bir diğer arayüzü genişletebilir. Aynı paket adında küçük bir sürüm artışı için veya eski bir paketin üzerine inşa edilecek yeni bir paket (örneğin bir satıcı uzantısı) için kullanılabilir. |
üretir | İstemciye değerleri döndüren bir arayüz yöntemini belirtir. İlkel olmayan bir değeri veya birden fazla değeri döndürmek için senkronize bir geri çağırma işlevi oluşturulur. |
arayüz | Yöntem ve türlerin toplanması. C++ veya Java'da bir sınıfa çevrildi. Bir arayüzdeki tüm yöntemler aynı yönde çağrılır: Bir istemci işlemi, bir sunucu işlemi tarafından uygulanan yöntemleri çağırır. |
Tek Yön | Bir HIDL yöntemine uygulandığında, yöntemin hiçbir değer döndürmediğini ve engellemediğini belirtir. |
paket | Bir sürümü paylaşan arayüzlerin ve veri türlerinin toplanması. |
geçiş | Sunucunun istemci tarafından dlopen paylaşılan bir kitaplık olduğu HIDL modu. Geçiş modunda, istemci ve sunucu aynı işlemdir ancak ayrı kod tabanlarıdır. Yalnızca eski kod tabanlarını HIDL modeline getirmek için kullanılır. Ayrıca bkz . Bağlanmış . |
sunucu | Bir arayüzün yöntemlerini uygulayan süreç. Ayrıca bkz . geçiş . |
Ulaşım | Verileri sunucu ve istemci arasında taşıyan HIDL altyapısı. |
versiyon | Bir paketin sürümü. Büyük ve küçük olmak üzere iki tam sayıdan oluşur. Küçük sürüm artışları türleri ve yöntemleri ekleyebilir (ancak değiştiremez). |
HIDL tasarımı
HIDL'nin amacı, Android çerçevesinin HAL'leri yeniden oluşturmaya gerek kalmadan değiştirilebilmesidir. HAL'ler satıcılar veya SOC üreticileri tarafından oluşturulacak ve cihaza bir /vendor
bölümü yerleştirilecek, böylece Android çerçevesinin kendi bölümünde HAL'leri yeniden derlemeden bir OTA ile değiştirilmesine olanak sağlanacak.
HIDL tasarımı aşağıdaki endişeleri dengeler:
- Birlikte çalışabilirlik . Çeşitli mimariler, araç zincirleri ve yapı konfigürasyonları ile derlenebilen işlemler arasında güvenilir şekilde birlikte çalışabilen arayüzler oluşturun. HIDL arayüzleri sürümlendirilmiştir ve yayınlandıktan sonra değiştirilemez.
- Yeterlik . HIDL, kopyalama işlemlerinin sayısını en aza indirmeye çalışır. HIDL tanımlı veriler, paketi açmadan kullanılabilecek C++ standart düzen veri yapılarında C++ koduna iletilir. HIDL ayrıca paylaşılan bellek arabirimleri sağlar ve RPC'ler doğası gereği yavaş olduğundan, HIDL, RPC çağrısı kullanmadan veri aktarmanın iki yolunu destekler: paylaşılan bellek ve Hızlı Mesaj Kuyruğu (FMQ).
- Sezgisel . HIDL, yalnızca RPC
in
kullanarak bellek sahipliğiyle ilgili çetrefilli sorunları önler (bkz. Android Arayüz Tanımlama Dili (AIDL) ); Yöntemlerden verimli bir şekilde döndürülemeyen değerler, geri çağırma işlevleri aracılığıyla döndürülür. Verilerin aktarım için HIDL'ye iletilmesi veya HIDL'den veri alınması, verilerin sahipliğini değiştirmez; mülkiyet her zaman çağıran işlevde kalır. Verilerin yalnızca çağrılan işlev süresince kalması gerekir ve çağrılan işlev geri döndükten hemen sonra yok edilebilir.
Geçiş modunu kullanma
Android'in önceki sürümlerini çalıştıran cihazları Android O'ya güncellemek için hem geleneksel (ve eski) HAL'leri, HAL'ye ciltlenmiş ve aynı işlem (geçiş) modlarında hizmet veren yeni bir HIDL arayüzüne sarabilirsiniz. Bu sarma hem HAL hem de Android çerçevesi için şeffaftır.
Geçiş modu yalnızca C++ istemcileri ve uygulamaları için kullanılabilir. Android'in önceki sürümlerini çalıştıran cihazlarda Java'da yazılmış HAL'ler yoktur, bu nedenle Java HAL'ler doğası gereği bağlayıcıdır.
Geçiş başlık dosyaları
Bir .hal
dosyası derlendiğinde, hidl-gen
ciltleyici iletişimi için kullanılan başlıklara ek olarak ekstra bir geçiş başlık dosyası BsFoo.h
üretir; bu başlık dlopen
fonksiyonları tanımlar. Geçiş HAL'leri çağrıldıkları aynı süreçte çalıştığından, çoğu durumda geçiş yöntemleri doğrudan işlev çağrısı (aynı iş parçacığı) tarafından çağrılır. oneway
yöntemler, HAL'in bunları işlemesini beklemeleri amaçlanmadığı için kendi iş parçacıklarında çalışır (bu, geçiş modunda oneway
yöntemler kullanan herhangi bir HAL'in iş parçacığı açısından güvenli olması gerektiği anlamına gelir).
Bir IFoo.hal
verildiğinde, BsFoo.h
, ek özellikler sağlamak için ( oneway
işlemlerin başka bir iş parçacığında çalıştırılması gibi) HIDL tarafından oluşturulan yöntemleri sarar. Bu dosya BpFoo.h
dosyasına benzer, ancak IPC çağrılarını bağlayıcı kullanarak iletmek yerine istenen işlevler doğrudan çağrılır. HAL'lerin gelecekteki uygulamaları, FooFast HAL ve FooAccurate HAL gibi birden fazla uygulama sağlayabilir . Bu gibi durumlarda, her ek uygulama için bir dosya oluşturulacaktır (örneğin, PTFooFast.cpp
ve PTFooAccurate.cpp
).
Geçiş HAL'lerinin bağlayıcı hale getirilmesi
Geçiş modunu destekleyen HAL uygulamalarını ciltleyebilirsiniz. HAL arayüzü verildiğinde abcd@MN::IFoo
iki paket oluşturulur:
-
abcd@MN::IFoo-impl
. HAL uygulamasını içerir veIFoo* HIDL_FETCH_IFoo(const char* name)
işlevini gösterir. Eski cihazlarda bu paketdlopen
ve uygulamaHIDL_FETCH_IFoo
kullanılarak başlatılır. Temel koduhidl-gen
ve-Lc++-impl
ve-Landroidbp-impl
kullanarak oluşturabilirsiniz. -
abcd@MN::IFoo-service
. Geçiş HAL'sini açar ve kendisini bağlayıcı hale getirilmiş bir hizmet olarak kaydederek aynı HAL uygulamasının hem doğrudan geçişli hem de bağlayıcı hale getirilmiş olarak kullanılmasına olanak tanır.
IFoo
türü göz önüne alındığında, IFoo
örneğine erişim sağlamak için sp<IFoo> IFoo::getService(string name, bool getStub)
çağırabilirsiniz. getStub
doğruysa getService
, HAL'yi yalnızca geçiş modunda açmaya çalışır. getStub
yanlışsa getService
, ciltlenmiş bir hizmet bulmaya çalışır; bu başarısız olursa, geçiş hizmetini bulmaya çalışır. getStub
parametresi, defaultPassthroughServiceImplementation
dışında hiçbir zaman kullanılmamalıdır. (Android O ile başlatılan cihazlar tamamen bağlayıcı cihazlar olduğundan, bir hizmetin doğrudan geçiş modunda açılmasına izin verilmez.)
HIDL dilbilgisi
Tasarım gereği HIDL dili C'ye benzer (ancak C ön işlemcisini kullanmaz). Aşağıda açıklanmayan tüm noktalama işaretleri ( =
ve |
'nin bariz kullanımı dışında) dilbilgisinin bir parçasıdır.
Not: HIDL kod stiliyle ilgili ayrıntılar için Kod Stili Kılavuzu'na bakın.
-
/** */
bir dokümantasyon yorumunu belirtir. Bunlar yalnızca tür, yöntem, alan ve numaralandırma değeri bildirimlerine uygulanabilir. -
/* */
çok satırlı bir yorumu belirtir. -
//
satırın sonuna yapılan yorumu belirtir.//
dışında yeni satırlar diğer boşluklarla aynıdır. - Aşağıdaki örnek dilbilgisinde,
//
dan satırın sonuna kadar olan metin dilbilgisinin bir parçası değildir, bunun yerine dilbilgisine ilişkin bir yorumdur. -
[empty]
, terimin boş olabileceği anlamına gelir. -
?
bir harfi veya terimi takip etmek isteğe bağlı olduğu anlamına gelir. -
...
belirtildiği gibi ayırıcı noktalama işaretiyle sıfır veya daha fazla öğe içeren diziyi belirtir. HIDL'de değişken argümanlar yoktur. - Virgüller dizi öğelerini ayırır.
- Noktalı virgül, son öğe de dahil olmak üzere her öğeyi sonlandırır.
- BÜYÜK HARF bir terminal değildir.
-
italics
,integer
veyaidentifier
gibi bir belirteç ailesidir (standart C ayrıştırma kuralları). -
constexpr
, C tarzı bir sabit ifadedir (1 + 1
ve1L << 3
gibi). -
import_name
, HIDL Sürüm Oluşturma'da açıklandığı gibi nitelenen bir paket veya arayüz adıdır. - Küçük
words
gerçek belirteçlerdir.
Örnek:
ROOT = PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... } // not for types.hal | PACKAGE IMPORTS ITEM ITEM... // only for types.hal; no method definitions ITEM = ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?; | safe_union identifier { UFIELD; UFIELD; ...}; | struct identifier { SFIELD; SFIELD; ...}; // Note - no forward declarations | union identifier { UFIELD; UFIELD; ...}; | enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar | typedef TYPE identifier; VERSION = integer.integer; PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION; PREAMBLE = interface identifier EXTENDS EXTENDS = <empty> | extends import_name // must be interface, not package GENERATES = generates (FIELD, FIELD ...) // allows the Binder interface to be used as a type // (similar to typedef'ing the final identifier) IMPORTS = [empty] | IMPORTS import import_name; TYPE = uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t | float | double | bool | string | identifier // must be defined as a typedef, struct, union, enum or import // including those defined later in the file | memory | pointer | vec<TYPE> | bitfield<TYPE> // TYPE is user-defined enum | fmq_sync<TYPE> | fmq_unsync<TYPE> | TYPE[SIZE] FIELD = TYPE identifier UFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...}; | struct identifier { FIELD; FIELD; ...}; | union identifier { FIELD; FIELD; ...}; | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SIZE = // Must be greater than zero constexpr ANNOTATIONS = [empty] | ANNOTATIONS ANNOTATION ANNOTATION = | @identifier | @identifier(VALUE) | @identifier(ANNO_ENTRY, ANNO_ENTRY ...) ANNO_ENTRY = identifier=VALUE VALUE = "any text including \" and other escapes" | constexpr | {VALUE, VALUE ...} // only in annotations ENUM_ENTRY = identifier | identifier = constexpr