HIDL

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.

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 ve IFoo* HIDL_FETCH_IFoo(const char* name) işlevini gösterir. Eski cihazlarda bu paket dlopen ve uygulama HIDL_FETCH_IFoo kullanılarak başlatılır. Temel kodu hidl-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 veya identifier gibi bir belirteç ailesidir (standart C ayrıştırma kuralları).
  • constexpr , C tarzı bir sabit ifadedir ( 1 + 1 ve 1L << 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