Google is committed to advancing racial equity for Black communities. See how.
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

HIDL

HAL接口定義語言或HIDL(發音為“ hide-1”)是一種接口描述語言(IDL),用於指定HAL及其用戶之間的接口。它允許指定收集到接口和程序包中的類型和方法調用。更廣泛地說,HIDL是一種用於在可以獨立編譯的代碼庫之間進行通信的系統。

HIDL旨在用於進程間通信(IPC)。進程之間的通信稱為Binderized 。對於必須鏈接到進程的庫,還可以使用直通模式 (Java不支持)。

HIDL指定數據結構和方法簽名,這些結構和方法簽名以接口(類似於類)的形式組織並收集到程序包中。儘管CID和Java程序員使用一組不同的關鍵字,但HIDL的語法看起來很熟悉。 HIDL還使用Java樣式的註釋。

HIDL設計

HIDL的目標是可以替換框架而無需重建HAL。 HAL將由供應商或SOC製造商構建,並放置在設備的/vendor分區中,從而使框架在其自己的分區中可以用OTA替換,而無需重新編譯HAL。

HIDL設計平衡了以下問題:

  • 互通性 。在可以使用各種體系結構,工具鍊和構建配置進行編譯的流程之間創建可靠的可互操作的接口。 HIDL接口已版本化,發布後無法更改。
  • 效率 。 HIDL嘗試最小化複製操作的數量。 HIDL定義的數據以C ++標準佈局數據結構傳遞到C ++代碼,這些結構無需解壓縮即可使用。 HIDL還提供了共享內存接口,並且由於RPC本質上較慢,因此HIDL支持兩種不使用RPC調用即可傳輸數據的方式:共享內存和快速消息隊列(FMQ)。
  • 直觀的 。 HIDL通過僅in RPC參數中使用避免了棘手的內存所有權問題(請參閱Android接口定義語言(AIDL) );無法通過方法有效返回的值將通過回調函數返回。無論是將數據傳遞到HIDL進行傳輸還是從HIDL接收數據都不會改變數據的所有權-所有權始終保留在調用函數中。數據僅需要在被調用函數的持續時間內保持不變,並且可以在被調用函數返回後立即銷毀。

使用直通模式

要將運行較早版本的Android的設備更新為Android O,您可以將常規(和傳統)HAL都包裝在新的HIDL接口中,該接口以綁定和相同進程(通過)模式為HAL提供服務。這種包裝對於HAL和Android框架都是透明的。

直通模式僅適用於C ++客戶端和實現。運行早期版本Android的設備沒有用Java編寫的HAL,因此Java HAL本質上是綁定的。

編譯.hal文件時, hidl-gen除了用於綁定程序通信的頭之外, hidl-gen生成一個額外的直通頭文件BsFoo.h 。此標頭定義的功能是dlopen編輯。由於直通HAL在與調用它們相同的過程中運行,因此在大多數情況下,直通方法是通過直接函數調用(相同的線程)來調用的。 oneway方法在它們自己的線程中運行,因為它們不打算等待HAL處理它們(這意味著在直通模式下使用oneway方法的任何HAL必須是線程安全的)。

給定一個IFoo.halBsFoo.h包裝HIDL生成的方法以提供其他功能(例如使oneway事務在另一個線程中運行)。該文件類似於BpFoo.h ,但是不是直接使用活頁夾傳遞調用IPC,而是直接調用所需的功能。 HAL的未來實現可能會提供多種實現,例如FooFast HAL和FooAccurate HAL。在這種情況下,將為每個其他實現創建一個文件(例如PTFooFast.cppPTFooAccurate.cpp )。

綁定直通HAL

您可以綁定支持直通模式的HAL實現。給定一個HAL接口abcd@MN::IFoo ,將創建兩個包:

  • abcd@MN::IFoo-impl 。包含HAL的實現,並公開函數IFoo* HIDL_FETCH_IFoo(const char* name) 。在傳統的設備,這個包是dlopen ED和執行使用實例化HIDL_FETCH_IFoo 。您可以使用hidl-gen-Lc++-impl-Landroidbp-impl生成基本代碼。
  • abcd@MN::IFoo-service 。打開直通HAL並將其自身註冊為綁定服務,從而可以將相同的HAL實現同時用作直通和綁定。

給定類型IFoo ,可以調用sp<IFoo> IFoo::getService(string name, bool getStub)來訪問IFoo實例。如果getStub為true,則getService僅嘗試在直通模式下打開HAL。如果getStub為false,則getService嘗試查找綁定服務;如果失敗,則嘗試查找直通服務。除非在defaultPassthroughServiceImplementation否則永遠不要使用getStub參數。 (使用Android O啟動的設備是完全綁定的設備,因此不允許以直通模式打開服務。)

HIDL語法

通過設計,HIDL語言類似於C(但不使用C預處理程序)。下文中未描述的所有標點符號(除了明顯使用=| )都是語法的一部分。

注意:有關HIDL代碼樣式的詳細信息,請參見《 代碼樣式指南》

  • /** */表示文檔註釋。這些只能應用於類型,方法,字段和枚舉值聲明。
  • /* */表示多行註釋。
  • //表示到行尾的註釋。除//之外,換行符與其他任何空格相同。
  • 在下面的示例語法中,從//到行尾的文本不是語法的一部分,而是對語法的註釋。
  • [empty]表示該術語可能為空。
  • ?字面量或術語後面的含義表示它是可選的。
  • ...表示包含零個或多個項目的序列,並帶有標點符號。 HIDL中沒有可變參數。
  • 逗號分隔序列元素。
  • 分號終止每個元素,包括最後一個元素。
  • 大寫字母是非終結符。
  • italics是令牌家族,例如integeridentifier (標準C解析規則)。
  • constexpr是C樣式的常量表達式(例如1 + 11L << 3 )。
  • import_name是軟件包或接口名稱,符合HIDL版本控制中所述
  • 小寫words是文字標記。

例:

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

術語

本節使用以下與HIDL相關的術語:

粘合劑指示HIDL正在用於通過類Binder機制實現的進程之間的遠程過程調用。另請參見passthrough
回調,異步由HAL用戶提供服務的接口,該接口傳遞給HAL(通過HIDL方法),並由HAL調用以隨時返回數據。
回調,同步從服務器的HIDL方法實現向客戶端返回數據。未用於返回void或單個原始值的方法。
客戶調用特定接口方法的過程。 HAL或框架進程可以是一個接口的客戶端,而可以是另一個接口的服務器。另請參見passthrough
延伸指示將方法和/或類型添加到另一個接口的接口。一個接口只能擴展另一個接口。可以用於同一軟件包名稱中的次要版本增量,也可以用於在較舊的軟件包上構建的新軟件包(例如,供應商擴展名)。
產生指示將值返回給客戶端的接口方法。要返回一個非原始值或多個值,將生成一個同步回調函數。
接口方法和類型的集合。轉換為C ++或Java類。接口中的所有方法都以相同的方向調用:客戶端進程調用服務器進程實現的方法。
單程當應用於HIDL方法時,表示該方法不返回任何值且不阻塞。
共享版本的接口和數據類型的集合。
直通服務器為共享庫的HIDL模式,由客戶端dlopen 。在直通模式下,客戶端和服務器是相同的過程,但代碼庫分開。僅用於將遺留代碼庫引入HIDL模型。另請參見Binderized
服務器實現接口方法的過程。另請參見passthrough
運輸在服務器和客戶端之間移動數據的HIDL基礎結構。
軟件包的版本。由兩個整數組成,主要和次要。較小的版本增量可能會添加(但不能更改)類型和方法。