HIDL C++

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");
}

defaultPassthroughServiceImplementationdlopen()提供的-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,則可以對其套用多個屬性)。