HIDL

HAL arabirim 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 belirlenmesine izin verir. Daha geniş anlamda, HIDL, bağımsız olarak derlenebilen kod tabanları arasında iletişim için bir sistemdir. Android 10'dan itibaren, HIDL kullanımdan kaldırılmıştır ve Android, AIDL'yi her yerde kullanmak için geçiş yapmaktadır.

HIDL, süreçler arası iletişim (IPC) için kullanılmak üzere tasarlanmıştır. HDL ile oluşturulan HALS, bağlayıcı süreçler arası iletişim (IPC) çağrılarını kullanarak diğer mimari katmanlarla iletişim kurabildikleri için ciltlenmiş 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 geçiş modu da mevcuttur (Java'da desteklenmez).

HIDL, paketler halinde toplanan arabirimlerde (bir sınıfa benzer) 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ı bir anahtar kelime grubu var. HIDL ayrıca Java tarzı ek açıklamalar kullanır.

terminoloji

Bu bölüm, aşağıdaki HIDL ile ilgili terimleri kullanır:

ciltlenmiş HIDL'nin, Binder benzeri bir mekanizma üzerinden uygulanan işlemler arasındaki uzak prosedür çağrıları için kullanıldığını gösterir. Ayrıca bkz .
geri arama, asenkron Bir HAL kullanıcısı tarafından sunulan, HAL'e geçirilen (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, senkron 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 arabirimin istemcisi ve diğerinin sunucusu olabilir. Ayrıca bkz .
uzanır Başka bir arabirime yöntemler ve/veya türler ekleyen bir arabirimi belirtir. Bir arabirim yalnızca bir başka arabirimi genişletebilir. Aynı paket adında küçük bir sürüm artışı için veya daha eski bir paket üzerine inşa edilecek yeni bir paket (örneğin bir satıcı uzantısı) için 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 eşzamanlı bir geri arama işlevi oluşturulur.
arayüz Yöntem ve türlerin toplanması. C++ veya Java'da bir sınıfa çevrildi. Bir arabirimdeki tüm yöntemler aynı yönde çağrılır: bir istemci süreci, bir sunucu süreci 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 paylaşılan bir kitaplık olduğu, istemci tarafından oluşturulan dlopen 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. Ciltlenmiş .
sunucu Bir arabirimin yöntemlerini uygulayan işlem. Ayrıca bkz .
Ulaşım Sunucu ve istemci arasında veri taşıyan HIDL altyapısı.
versiyon 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ştirmez).

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 cihazda bir /vendor bölümüne yerleştirilecek, böylece Android çerçevesinin kendi bölümünde, HAL'leri yeniden derlemeden bir OTA ile değiştirilmesi sağlanacaktır.

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 versiyonlanmıştı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 yerleşim veri yapılarında C++ koduna teslim edilir. HIDL ayrıca paylaşılan bellek arabirimleri sağlar ve RPC'ler doğal olarak 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 zorlu bellek sahipliği sorunlarını önler (bkz. Android Arabirim 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. Ne aktarım için HIDL'ye veri iletmek ne de HIDL'den veri almak verinin sahipliğini değiştirmez; sahiplik her zaman arama işlevinde kalır. Verilerin yalnızca çağrılan işlev süresince kalıcı olması 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 arabirimine 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.

Bir .hal dosyası derlendiğinde, hidl-gen , bağlayıcı iletişimi için kullanılan başlıklara ek olarak, fazladan bir geçiş başlık dosyası BsFoo.h üretir; bu başlık, dlopen edilecek işlevleri tanımlar. Geçişli HAL'ler çağrıldıkları aynı işlemde ç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. tek yönlü yöntemler, oneway bunları işlemesini beklemeleri amaçlanmadığı için kendi iş parçacığında çalışır (bu, geçiş modunda oneway yöntemleri kullanan tüm HAL'lerin iş parçacığı için güvenli olması gerektiği anlamına gelir).

Bir IFoo.hal verildiğinde, 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 binder kullanarak IPC çağrılarını 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 ).

Geçiş HAL'lerini bağlama

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 ve IFoo* HIDL_FETCH_IFoo(const char* name) işlevini sunar. Eski cihazlarda, bu paket HIDL_FETCH_IFoo dlopen başlatılır. hidl-gen ve -Lc++-impl ve -Landroidbp-impl impl kullanarak temel kodu oluşturabilirsiniz.
  • abcd@MN::IFoo-service . HAL geçişini açar ve kendisini ciltlenmiş bir hizmet olarak kaydederek, aynı HAL uygulamasının hem geçiş hem de ciltlenmiş olarak kullanılmasını sağlar.

IFoo türü verildiğinde, bir IFoo örneğine erişmek için sp<IFoo> IFoo::getService(string name, bool getStub) IFoo . getStub true ise, getService HAL'ı 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 asla kullanılmamalıdır. (Android O ile başlatılan cihazlar tamamen ciltlenmiş cihazlardır, bu nedenle bir hizmetin 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 | '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ılavuzuna bakın.

  • /** */ bir belge açıklamasını belirtir. Bunlar yalnızca tür, yöntem, alan ve enum değeri bildirimlerine uygulanabilir.
  • /* */ çok satırlı bir yorumu belirtir.
  • // satırın sonuna kadar bir yorumu belirtir. // dışında, yeni satırlar diğer boşluklarla aynıdır.
  • Aşağıdaki dilbilgisi örneğinde, // ile satırın sonuna kadar olan metin dilbilgisinin bir parçası değil, bunun yerine dilbilgisi hakkında bir yorumdur.
  • [empty] , terimin boş olabileceği anlamına gelir.
  • ? bir hazır bilgi veya terimin ardından isteğe bağlı olduğu anlamına gelir.
  • ... , sıfır veya daha fazla öğe içeren diziyi, belirtildiği gibi ayıran noktalama işaretleriyle belirtir. HIDL'de değişken argümanlar yoktur.
  • Virgüller sıra öğelerini ayırır.
  • Noktalı virgüller, son öğe de dahil olmak üzere her öğeyi sonlandırır.
  • BÜYÜK HARF bir terminal dışıdır.
  • italics , integer veya identifier gibi bir belirteç ailesidir (standart C ayrıştırma kuralları).
  • constexpr bir C stili sabit ifadesidir ( 1 + 1 ve 1L << 3 gibi).
  • import_name , HIDL Sürüm Oluşturma bölümünde açıklandığı gibi nitelenen bir paket veya arabirim adıdır.
  • Küçük harfli 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