HIDL 是圍繞介面建構而成,介面是一種抽象類型,用於定義以物件為導向的語言行為。每個介面都是套件的一部分。
套件
套件名稱可包含 package.subpackage
等子層級。已發布 HIDL 套件的根目錄為 hardware/interfaces
或 vendor/vendorName
(例如 Pixel 裝置的 vendor/google
)。套件名稱會在根目錄下建立一或多個子目錄;定義套件的所有檔案都位於同一個目錄中。舉例來說,package android.hardware.example.extension.light@2.0
可在 hardware/interfaces/example/extension/light/2.0
下方找到。
下表列出套件前置字串和位置:
套件前置字串 | 位置 | 介面類型 |
---|---|---|
android.hardware.* |
hardware/interfaces/* |
HAL |
android.frameworks.* |
frameworks/hardware/interfaces/* |
架構/ 相關 |
android.system.* |
system/hardware/interfaces/* |
system/ related |
android.hidl.* |
system/libhidl/transport/* |
Core |
套件目錄包含副檔名為 .hal
的檔案。每個檔案都必須包含 package
陳述式,其中會命名檔案所屬的套件和版本。如果有 types.hal
檔案,則不會定義介面,而是定義套件中每個介面可存取的資料類型。
介面定義
除了 types.hal
之外,每個其他 .hal
檔案都會定義介面。介面通常會定義如下:
interface IBar extends IFoo { // IFoo is another interface // embedded types struct MyStruct {/*...*/}; // interface methods create(int32_t id) generates (MyStruct s); close(); };
沒有明確 extends
宣告的介面會從 android.hidl.base@1.0::IBase
隱含延伸 (類似於 Java 中的 java.lang.Object
)。隱含匯入的 IBase 介面會宣告幾種保留方法,這些方法不應且無法在使用者定義的介面中重新宣告或以其他方式使用。這些方法包括:
ping
interfaceChain
interfaceDescriptor
notifySyspropsChanged
linkToDeath
unlinkToDeath
setHALInstrumentation
getDebugInfo
debug
getHashChain
匯入程序
import
陳述式是 HIDL 機制,可存取其他套件中的套件介面和類型。import
陳述式涉及兩個實體:
- 匯入實體,可以是套件或介面
- 已匯入的實體,可以是套件或介面
匯入實體取決於 import
陳述式的所在位置。如果陳述式位於套件的 types.hal
中,則整個套件都能看到匯入的內容,這就是套件層級匯入。如果陳述式位於介面檔案中,匯入實體就是介面本身,這是介面層級匯入。
匯入實體的決定因素是 import
關鍵字後面的值。值不必是完整的名稱;如果省略元件,系統會自動填入目前套件中的資訊。對於完全限定的值,系統支援下列匯入情況:
- 整個套件匯入作業。如果值是套件名稱和版本 (以下說明語法),則整個套件會匯入匯入實體。
- 部分匯入。如果值為:
- 介面、套件的
types.hal
和該介面會匯入匯入實體。 - 在
types.hal
中定義的 UDT,則只會將該 UDT 匯入匯入實體 (不會匯入types.hal
中的其他類型)。
- 介面、套件的
- 僅匯入類型。如果值使用上述部分匯入的語法,但使用關鍵字
types
而非介面名稱,則只會匯入指定套件的types.hal
中的 UDT。
匯入實體可存取以下項目的組合:
- 匯入套件在
types.hal
中定義的常見 UDT; - 匯入套件的介面 (針對整個套件匯入) 或指定介面 (針對部分匯入),用於叫用、將句柄傳遞至這些介面和/或從這些介面繼承。
匯入陳述式使用完整合格型別名稱語法,提供要匯入的套件或介面的名稱和版本:
import android.hardware.nfc@1.0; // import a whole package import android.hardware.example@1.0::IQuux; // import an interface and types.hal import android.hardware.example@1.0::types; // import just types.hal
介面繼承
介面可以是先前定義介面的擴充功能。擴充功能可分為下列三種類型:
- 介面可為另一個介面新增功能,並保留其 API 不變。
- 套件可以為另一個套件新增功能,並保留其 API 不變。
- 介面可以從套件或特定介面匯入類型。
介面只能擴充一個其他介面 (不得重複繼承)。套件中每個介面 (子版本號碼非零) 都必須擴充套件先前版本中的介面。舉例來說,如果 derivative
套件 4.0 版的介面 IBar
是基於 (擴充) original
套件 1.2 版的介面 IFoo
,且已建立 original
套件 1.3 版,IBar
4.1 版就無法擴充 IFoo
1.3 版。IBar
4.1 版必須擴充 IBar
4.0 版,而 IBar
4.0 版與 IFoo
1.2 版相關聯。IBar
5.0 版可視需要擴充 IFoo
1.3 版。
介面擴充功能不會在產生的程式碼中暗示程式庫依附性或跨 HAL 的納入,而是會在 HIDL 層級匯入資料結構和方法定義。HAL 中的每個方法都必須在該 HAL 中實作。
供應商額外資訊
在某些情況下,供應商擴充功能會實作為基礎物件的子類別,代表擴充的核心介面。同一個物件會在基礎 HAL 名稱和版本下註冊,也會在擴充功能的 (供應商) HAL 名稱和版本下註冊。
版本管理
套件會加上版本號碼,介面則會顯示套件版本。版本會以兩個整數表示,分別為主要.次要。
- 主要版本不具回溯相容性。遞增主要版本號碼會將次要版本號碼重設為 0。
- 子版本可回溯相容。增加次要版本號碼,表示新版本與舊版本完全回溯相容。您可以新增資料結構和方法,但不得變更現有的資料結構或方法簽章。
裝置上可以同時存在多個 HAL 的主要版本或次要版本。不過,子版本應優先於主要版本,因為可與先前子版本介面搭配使用的用戶端程式碼,也能與該介面的後續子版本搭配使用。如要進一步瞭解版本管理和供應商擴充功能,請參閱「HIDL 版本管理」。
介面版面配置摘要
本節將概述如何管理 HIDL 介面套件 (例如 hardware/interfaces
),並整合整個 HIDL 專區中顯示的資訊。閱讀本文前,請先熟悉 HIDL 版本化、使用 hidl-gen 進行雜湊的概念、一般使用 HIDL 的詳細資訊,以及下列定義:
字詞 | 定義 |
---|---|
應用程式二進位檔介面 (ABI) | 應用程式設計介面,以及所需的任何二進位連結。 |
完整名稱 (fqName) | 用於區分 HIDL 類型的名稱。範例:android.hardware.foo@1.0::IFoo 。 |
包裹 | 包含 HIDL 介面和類型的套件。範例:android.hardware.foo@1.0 。 |
套件根目錄 | 包含 HIDL 介面的根套件。範例:HIDL 介面 android.hardware 位於套件根目錄 android.hardware.foo@1.0 中。 |
套件根路徑 | 套件根目錄對應至 Android 原始碼樹中的哪個位置。 |
如需更多定義,請參閱 HIDL 術語。
您可以透過套件根目錄對應項目和完整合格名稱找到每個檔案
套件根目錄會指定為 hidl-gen
的引數 -r android.hardware:hardware/interfaces
。舉例來說,如果套件是 vendor.awesome.foo@1.0::IFoo
,而 hidl-gen
是傳送 -r vendor.awesome:some/device/independent/path/interfaces
,則介面檔案應位於 $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal
中。
實際上,建議名稱為 awesome
的供應商或原始設備製造商 (OEM) 將標準介面放在 vendor.awesome
中。選取套件路徑後,請勿變更,因為這會整合至介面的 ABI。
套件路徑對應不得重複
舉例來說,如果您有 -rsome.package:$PATH_A
和 -rsome.package:$PATH_B
,$PATH_A
必須等於 $PATH_B
,才能提供一致的介面目錄 (這也讓版本介面更容易管理)。
套件根目錄必須有版本管理檔案
如果您建立 -r vendor.awesome:vendor/awesome/interfaces
等套件路徑,也應建立 $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt
檔案,其中應包含使用 hidl-gen
中的 -Lhash
選項建立的介面雜湊值 (詳見「使用 hidl-gen 進行雜湊處理」一文)。
介面會放在裝置獨立的位置
實際上,我們建議在分支版本之間共用介面。這可讓您在不同裝置和用途中盡可能重複使用程式碼,並對程式碼進行測試。