Android O 重新架構了 Android 作業系統,以在獨立於裝置的 Android 平台與特定於裝置和供應商的程式碼之間定義清晰的介面。 Android 已經以 HAL 介面的形式定義了許多此類接口,在hardware/libhardware
中定義為 C 頭檔。 HIDL 將這些 HAL 介面替換為穩定的版本化接口,這些接口可以是 C++(如下所述)或Java中的客戶端和伺服器端 HIDL 介面。
本節中的頁面介紹 HIDL 介面的 C++ 實現,包括有關hidl-gen
編譯器從 HIDL .hal
檔案自動產生的檔案、這些檔案的打包方式以及如何將這些檔案與 C++ 程式碼整合的詳細資訊使用它們。
客戶端和伺服器實現
HIDL 介面有客戶端和伺服器實作:
- HIDL 介面的客戶端是透過呼叫介面上的方法來使用該介面的程式碼。
- 伺服器是 HIDL 介面的實現,它接收來自客戶端的呼叫並傳回結果(如果需要)。
從libhardware
HAL 轉換到 HIDL HAL 時,HAL 實作成為伺服器,而呼叫 HAL 的程序成為客戶端。預設實作可以同時服務直通和綁定化 HAL,並且可以隨著時間的推移而改變:
圖 1.舊版 HAL 的開發進度。
創建 HAL 客戶端
首先在 makefile 中包含 HAL 函式庫:
- 製作:
LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
- 宋:
shared_libs: [ …, android.hardware.nfc@1.0 ]
接下來,包含 HAL 頭檔:
#include <android/hardware/nfc/1.0/IFoo.h> … // in code: sp<IFoo> client = IFoo::getService(); client->doThing();
建立 HAL 伺服器
要建立 HAL 實現,您必須擁有代表 HAL 的.hal
文件,並且已經在hidl-gen
上使用-Lmakefile
或-Landroidbp
為 HAL 產生了 makefile( ./hardware/interfaces/update-makefiles.sh
執行此操作內部HAL文件,是一個很好的參考)。從libhardware
傳輸 HAL 時,您可以使用 c2hal 輕鬆完成許多此類工作。
若要建立實現 HAL 所需的檔案:
PACKAGE=android.hardware.nfc@1.0 LOC=hardware/interfaces/nfc/1.0/default/ m -j hidl-gen hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE
為了讓 HAL 在直通模式下運作,您必須將函數HIDL_FETCH_IModuleName駐留在/(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl( OPTIONAL_IDENTIFIER ).so
其中OPTIONAL_IDENTIFIER是標識直通實現的字串。上述指令會自動滿足直通模式要求,這些指令也會建立android.hardware.nfc@1.0-impl
目標,但可以使用任何擴充。例如android.hardware.nfc@1.0-impl-foo
使用-foo
來區分自己。
如果 HAL 是次要版本或另一個 HAL 的擴展,則應使用基本 HAL 來命名該二進位。例如, android.hardware.graphics.mapper@2.1
實作仍應位於名為android.hardware.graphics.mapper@2.0-impl( OPTIONAL_IDENTIFIER )
的二進位檔案中。通常,此處的OPTIONAL_IDENTIFIER將包含實際的 HAL 版本。透過這樣命名二進位文件,2.0 客戶端可以直接檢索它,2.1 用戶端可以向上轉換實作。
接下來,填寫功能存根並設定守護程序。守護程式程式碼範例(支援直通):
#include <hidl/LegacySupport.h> int main(int /* argc */, char* /* argv */ []) { return defaultPassthroughServiceImplementation<INfc>("nfc"); }
defaultPassthroughServiceImplementation
將dlopen()
提供的-impl
函式庫並將其作為綁定服務提供。範例守護程式程式碼(對於純綁定服務):
int main(int /* argc */, char* /* argv */ []) { // This function must be called before you join to ensure the proper // number of threads are created. The threadpool will never exceed // size one because of this call. ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/); sp<INfc> nfc = new Nfc(); const status_t status = nfc->registerAsService(); if (status != ::android::OK) { return 1; // or handle error } // Adds this thread to the threadpool, resulting in one total // thread in the threadpool. We could also do other things, but // would have to specify 'false' to willJoin in configureRpcThreadpool. ::android::hardware::joinRpcThreadpool(); return 1; // joinRpcThreadpool should never return }
這個守護程式通常位於$PACKAGE + "-service-suffix"
中(例如android.hardware.nfc@1.0-service
),但它可以位於任何地方。特定 HAL 類別的sepolicy是屬性hal_<module>
(例如hal_nfc)
。此屬性必須套用於執行特定 HAL 的守護程式(如果相同程式服務於多個 HAL,則可以對其套用多個屬性)。