HAL arabirimi tanımlama dili veya HIDL, bir HAL ile kullanıcıları arasındaki arabirimi belirtmek için bir arabirim tanımlama dilidir (IDL). HIDL, arabirimler ve paketler halinde toplanan türlerin ve yöntem çağrılarının belirtilmesine izin verir. Daha genel olarak, HIDL, bağımsız olarak derlenebilen kod tabanları arasında iletişim kurmak için bir sistemdir. Android 10'dan itibaren HIDL kullanımdan kaldırılmıştır ve Android, AIDL'yi her yerde kullanmak üzere geçiş yapmaktadır.
HIDL, süreçler arası iletişim (IPC) için kullanılmak üzere tasarlanmıştır. HDL ile oluşturulan HAL'ler, bağlayıcı süreçler arası iletişim (IPC) çağrılarını kullanarak diğer mimari katmanlarla iletişim kurabilmeleri açısından bağlayıcı hale getirilmiş HAL'ler olarak adlandırılır. Bağlanmış HAL'ler, onları kullanan istemciden ayrı bir işlemde çalışır. Bir işleme bağlanması gereken kitaplıklar için bir düz geçiş modu da mevcuttur (Java'da desteklenmez).
HIDL, paketler halinde toplanan (bir sınıfa benzer) arabirimlerde düzenlenen veri yapılarını ve yöntem imzalarını belirtir. HIDL'nin sözdizimi, C++ ve Java programcılarına tanıdık geliyor, ancak farklı anahtar sözcüklerle. HIDL ayrıca Java tarzı notlar kullanır.
terminoloji
Bu bölümde aşağıdaki HIDL ile ilgili terimler kullanılmaktadır:
ciltlenmiş | HIDL'nin, Binder benzeri bir mekanizma üzerinden uygulanan işlemler arasındaki uzak yordam çağrıları için kullanıldığını gösterir. Ayrıca bkz. geçiş . |
---|---|
geri arama, eşzamansız | Bir HAL kullanıcısı tarafından sunulan, HAL'a iletilen (bir HIDL yöntemi kullanılarak) ve herhangi bir zamanda veri döndürmek için HAL tarafından çağrılan arabirim. |
geri arama, senkronize | Bir sunucunun HIDL yöntemi uygulamasından istemciye veri döndürür. Void veya tek bir ilkel değer döndüren yöntemler için kullanılmaz. |
müşteri | Belirli bir arabirimin yöntemlerini çağıran işlem. 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 arabirime yöntemler ve/veya türler ekleyen bir arabirimi belirtir. Bir arabirim yalnızca bir diğer arabirimi genişletebilir. Aynı paket adındaki küçük bir sürüm artışı için veya daha eski bir paket üzerine inşa edilecek yeni bir paket için (örn. satıcı uzantısı) kullanılabilir. |
üretir | İstemciye değer döndüren bir arabirim yöntemini belirtir. İlkel olmayan bir değer veya birden fazla değer döndürmek için senkronize bir geri arama işlevi oluşturulur. |
arayüz | Yöntem ve türlerin toplanması. C++ veya Java'da bir sınıfa çevrilmiştir. Bir arabirimdeki 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çit | Sunucunun, istemci tarafından açılan paylaşılan bir kitaplık olduğu dlopen modu. Düz 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. Ciltlenmiş . |
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ı. |
sürüm | Bir paketin sürümü. Majör ve minör olmak üzere iki tam sayıdan oluşur. Küçük sürüm artışları, türler ve yöntemler ekleyebilir (ancak değiştiremez). |
HIDL tasarımı
HIDL'nin amacı, HAL'leri yeniden oluşturmak zorunda kalmadan Android çerçevesinin değiştirilebilmesidir. HAL'ler, satıcılar veya SOC oluşturucular tarafından oluşturulacak ve cihazda bir /vendor
bölümüne yerleştirilerek, kendi bölümündeki Android çerçevesinin HAL'leri yeniden derlemeden bir OTA ile değiştirilmesini sağlayacak.
HIDL tasarımı aşağıdaki endişeleri dengeler:
- Birlikte çalışabilirlik Çeşitli mimariler, araç zincirleri ve yapı yapılandırmalarıyla derlenebilen süreçler arasında güvenilir şekilde birlikte çalışabilir arabirimler oluşturun. HIDL arayüzleri sürümlüdür ve yayınlandıktan sonra değiştirilemez.
- Verimlilik HIDL, kopyalama işlemlerinin sayısını en aza indirmeye çalışır. HIDL tanımlı veriler, paketi açmadan kullanılabilen C++ standart düzen veri yapılarında C++ koduna teslim edilir. HIDL ayrıca paylaşılan bellek arabirimleri sağlar ve RPC'ler doğası gereği biraz yavaş olduğundan, HIDL bir RPC çağrısı kullanmadan veri aktarmanın iki yolunu destekler: paylaşılan bellek ve Hızlı Mesaj Kuyruğu (FMQ).
- Sezgisel HIDL
in
yalnızca RPC parametrelerinde 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 arama 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—sahiplik her zaman çağıran işlevde kalır. Verilerin yalnızca çağrılan işlev süresince devam etmesi 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'a 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 ile yazılmış HAL'ler yoktur, bu nedenle Java HAL'leri doğal olarak ciltlenir.
Geçişli başlık dosyaları
Bir .hal
dosyası derlendiğinde, hidl-gen
ciltleyici iletişimi için kullanılan başlıklara ek olarak fazladan bir düz geçişli başlık dosyası BsFoo.h
üretir; bu başlık, kaldırılacak dlopen
tanımlar. Geçişli HAL'ler çağrıldıkları süreçte çalıştıkları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. tek yönlü yöntemler, oneway
onları işlemesini beklemeyi amaçlamadığından kendi iş parçacığında çalışır (bu, geçiş modunda tek yönlü yöntemleri kullanan herhangi bir oneway
iş parçacığı açısından güvenli olması gerektiği anlamına gelir).
Bir IFoo.hal
, BsFoo.h
ek özellikler sağlamak için HIDL tarafından oluşturulan yöntemleri sarar ( oneway
işlemlerin başka bir iş parçacığında çalıştırılması gibi). Bu dosya BpFoo.h
dosyasına benzer, ancak IPC çağrılarını binder kullanarak iletmek yerine, istenen işlevler doğrudan çağrılır. HAL'lerin gelecekteki uygulamaları, FooFast HAL ve FooAccurate HAL gibi birden çok uygulama sağlayabilir . Bu gibi durumlarda, her ek uygulama için bir dosya oluşturulur (örneğin, PTFooFast.cpp
ve PTFooAccurate.cpp
).
Bağlayıcı geçiş HAL'leri
Düz geçiş modunu destekleyen HAL uygulamalarını ciltleyebilirsiniz. Bir HAL arabirimi 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 paketHIDL_FETCH_IFoo
dlopen
başlatılır. Temel koduhidl-gen
ve-Lc++-impl
ve-Landroidbp-impl
impl kullanarak oluşturabilirsiniz. -
abcd@MN::IFoo-service
. Düz geçişli HAL'ı açar ve kendisini ciltlenmiş bir hizmet olarak kaydederek aynı HAL uygulamasının hem geçişli hem de bağlayıcılı olarak kullanılmasını sağlar.
IFoo
türü verildiğinde, bir IFoo örneğine erişim elde etmek için sp<IFoo> IFoo::getService(string name, bool getStub)
IFoo
. getStub
true ise, getService
HAL'ı yalnızca düz geçiş modunda açmaya çalışır. getStub
false ise, getService
ciltlenmiş bir hizmet bulmaya çalışır; bu başarısız olursa, doğrudan 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 ciltlenmiş cihazlardır, bu nedenle 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 önişlemcisini kullanmaz). Aşağıda açıklanmayan tüm noktalama işaretleri ( =
ve |
'in bariz kullanımı dışında) dilbilgisinin bir parçasıdır.
Not: HIDL kodu stiliyle ilgili ayrıntılar için bkz. Kod Stili Kılavuzu .
-
/** */
bir belge açıklamasını 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 bir yorum belirtir.//
dışında, yeni satırlar diğer boşluklarla aynıdır. - Aşağıdaki örnek dilbilgisinde,
//
'den satırın sonuna kadar olan metin dilbilgisinin bir parçası değil, bunun yerine dilbilgisi üzerine bir yorumdur. -
[empty]
, terimin boş olabileceği anlamına gelir. -
?
bir değişmez veya terimden sonra isteğe bağlı olduğu anlamına gelir. -
...
belirtildiği gibi ayırıcı noktalama işaretleri ile sıfır veya daha fazla öğe içeren sırayı belirtir. HIDL'de değişken argümanlar yoktur. - Sıra öğelerini virgülle ayırın.
- Noktalı virgüller, son öğe dahil her öğeyi sonlandırır.
- BÜYÜK HARF bir terminal değildir.
-
italics
,integer
veyaidentifier
(standart C ayrıştırma kuralları) gibi bir belirteç ailesidir. -
constexpr
, C tarzı bir sabit ifadedir (1 + 1
ve1L << 3
gibi). -
import_name
, HIDL Sürüm Oluşturma'da açıklandığı gibi nitelendirilen bir paket veya arabirim adıdır. - Küçük harfli
words
gerçek belirteçlerdir.
Misal:
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