Android HIDL 詳解


copy from :  https://blog.csdn.net/shift_wwx/article/details/86514997

 

前言
Android Treble 簡介 一文中提到了Android O之后使用Treble的架構,為了解決Android 系統的碎片化問題和提高系統更新的效率,減少了framework 和HAL 的耦合性,進而引出了HIDL 的概念。本文將詳細的總結HIDL 的使用。

本文代碼基於:Android P

 

HIDL簡介
HIDL 全稱為HAL interface definition language(發音為“hide-l”)是用於指定 HAL 和其用戶之間的接口的一種接口描述語言 (IDL)。

HIDL 的目標是,框架可以在無需重新構建 HAL 的情況下進行替換。HAL 將由供應商或 SOC 制造商構建,放置在設備的 /vendor 分區中,這樣一來,框架就可以在其自己的分區中通過 OTA 進行替換,而無需重新編譯 HAL,這也是Project Treble框架設計而誕生的。

HIDL對比與AIDL 
相同 不同
AIDL HIDL
都是使用Binder 機制進行IPC

 

都使用service manager進行管控

文件的后綴為 aidl 文件的后綴為 hal
適用於框架/應用 之間的IPC
適用於框架/HAL 進程之間的IPC

適用於OEM 進程之間的IPC

使用設備節點為/dev/binder
使用設備節點為/dev/hwbinder

或 /dev/vndbinder

語言實現方式不同(例如數據類型、types.hal等)
HIDL 設計原則
HIDL 的目標是,框架可以在無需重新構建 HAL 的情況下進行替換。HAL 將由供應商或 SOC 制造商構建,放置在設備的 /vendor 分區中,這樣一來,框架就可以在其自己的分區中通過 OTA 進行替換,而無需重新編譯 HAL。

HIDL 設計在以下方面之間保持了平衡:

互操作性。在可以使用各種架構、工具鏈和編譯配置來編譯的進程之間創建可互操作的可靠接口。HIDL 接口是分版本的,發布后不得再進行更改。
效率。HIDL 會嘗試盡可能減少復制操作的次數。HIDL 定義的數據以 C++ 標准布局數據結構傳遞至 C++ 代碼,無需解壓,可直接使用。此外,HIDL 還提供共享內存接口;由於 RPC 本身有點慢,因此 HIDL 支持兩種無需使用 RPC 調用的數據傳輸方法:共享內存和快速消息隊列 (FMQ)。
直觀。通過僅針對 RPC 使用 in 參數,HIDL 避開了內存所有權這一棘手問題(請參閱 Android 接口定義語言 (AIDL));無法從方法高效返回的值將通過回調函數返回。無論是將數據傳遞到 HIDL 中以進行傳輸,還是從 HIDL 接收數據,都不會改變數據的所有權,也就是說,數據所有權始終屬於調用函數。數據僅需要在函數被調用期間保留,可在被調用的函數返回數據后立即清除。
 

HIDL 類型
Passthrough
兼容之前的HAL 使用方式(在同一個進程)。

要將運行早期版本的 Android 的設備更新為使用 Android O,您可以將慣用的(和舊版)HAL 封裝在一個新 HIDL 接口中,該接口將在綁定式模式和同進程(直通)模式提供 HAL。這種封裝對於 HAL 和 Android 框架來說都是透明的。

直通模式僅適用於 C++ 客戶端和實現。運行早期版本的 Android 的設備沒有用 Java 編寫的 HAL,因此 Java HAL 自然而然經過 Binder 化。

Binderized
使用Binder 方式進行IPC(在不同進程)。

在使用HIDL 的時候需要有兩個軟件包,一個是FQName-impl,一個是FQName-service。FQName-impl一般是HAL 實現的部分或者是鏈接HAL的部分,FQName-service 就是service 端。

當然,為了兼容之前的HAL 舊版本和接口的統一,FQName-service 也可以是簡單的直通(passthrough)模式。例如:

int main() {
return defaultPassthroughServiceImplementation<INfc>();
}
如果是這樣的話,需要在FQName-impl 中暴露HIDL_FETCH_*接口,例如:(這里用NFC 為例,HIDL 文件名為INfc.hal)

extern "C" INfc* HIDL_FETCH_INfc(const char* name);
 

當然,如果采用進程的方式FQName-service 的main 函數修改為:

#define LOG_TAG "android.hardware.cfc@1.0-service"

#include <android/hardware/nfc/1.0/INfc.h>
#include <hidl/LegacySupport.h>
#include "Nfc.h"
using android::hardware::nfc::V1_0::INfc;
using android::hardware::nfc::V1_0::implementation::Nfc;
using android::hardware::defaultPassthroughServiceImplementation;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;

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.
configureRpcThreadpool(1 /*threads*/, true /*willJoin*/);

sp<INfc> nfc = new Nfc();

if(android::OK != nfc->registerAsService())
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.
joinRpcThreadpool();

return 1; // joinRpcThreadpool should never return
}
如果有一個 INfc,您可以調用 sp<INfc> INfc::getService(string name, bool getStub),以獲取對 INfc 實例的訪問權限。如果 getStub 為 True,則 getService 會嘗試僅在直通模式下打開 HAL。如果 getStub 為 False,則 getService 會嘗試找到 Binder 化服務;如果未找到,則它會嘗試找到直通式服務。除了在 defaultPassthroughServiceImplementation 中,其余情況一律不得使用 getStub 參數。(搭載 Android O 的設備是完全 Binder 化的設備,因此不得在直通模式下打開服務。)

 

HIDL 工具 hidl_gen
代碼目錄:system/tools/hidl

cc_library_host_shared {
name: "libhidl-gen",
defaults: ["hidl-gen-defaults"],
srcs: [
"Annotation.cpp",
"ArrayType.cpp",
"CompoundType.cpp",
"ConstantExpression.cpp",
"DeathRecipientType.cpp",
"DocComment.cpp",
"EnumType.cpp",
"HandleType.cpp",
"HidlTypeAssertion.cpp",
...
在使用的時候可以直接使用out/host/linux-x86/bin/hidl-gen 或者使用:

./build/setenv.sh
lunch
lunch 之后可以直接使用hidl-gen,因為這個時候已經將bin 的目錄添加到了環境變量中了

詳細hidl-gen 使用可以看另一篇博文:Android HIDL 中 hidl-gen使用

 

HIDL 代碼規范
HIDL 是接口描述語言,只要是編程語言就會涉及到編寫的規范,例如文件名、包名、變量、接口、數據類型、版本等等。

詳細的代碼規范可以看另一篇博文:Android HIDL 編程規范

 

HIDL 接口與package
HIDL 是圍繞接口進行編譯的,接口是面向對象的語言使用的一種用來定義行為的抽象類型。每個接口都是軟件包的一部分。

例如:

package android.hardware.nfc@1.0;

import INfcClientCallback;

interface INfc {
@entry
@callflow(next={"write", "coreInitialized", "prediscover", "powerCycle", "controlGranted"})
open(INfcClientCallback clientCallback) generates (NfcStatus status);
要使用接口INfc,必須要確定其package以及在interface 下定義所使用的接口。通過Android HIDL 編程規范 得知package的定義是有一定的規范的(由PACKAGE、MODULE、SUBMODULE、VERSION等組成),interface 的定義也有特定的規則。

 

再例如:nfc 中的types.hal

package android.hardware.nfc@1.0;

@export(name="", value_prefix="HAL_NFC_", value_suffix="_EVT")
enum NfcEvent : uint32_t {
OPEN_CPLT = 0,
CLOSE_CPLT = 1,
POST_INIT_CPLT = 2,
PRE_DISCOVER_CPLT = 3,
REQUEST_CONTROL = 4,
RELEASE_CONTROL = 5,
ERROR = 6
};
types.hal 定義的是需要使用的數據類型,並沒有定義interface,這也是types.hal 的特殊之處。

詳細內容可以看另一篇博文:Android HIDL 接口和軟件包使用

 

HIDL 中使用的共享庫
libhidlbase 包含標准 HIDL 數據類型。除非您的接口只包含直接映射到 C++ 基元的基元,否則您還必須鏈接到此庫:
LOCAL_SHARED_LIBRARIES += libhidlbase
 

libhidltransport 通過不同的 RPC/IPC 機制處理 HIDL 調用的傳輸。您必須始終鏈接到此庫:
LOCAL_SHARED_LIBRARIES += libhidltransport
 

libhwbinder 您還必須鏈接到此庫:
LOCAL_SHARED_LIBRARIES += libhwbinder
 

libfmq 要使用快速消息隊列 IPC,您還必須鏈接到此庫。
LOCAL_SHARED_LIBRARIES += libfmq
 

HIDL 中的數據類型
在另一篇博文會詳細描述HelloWorld 在HIDL中的使用:Android HIDL 中的數據類型

 

HIDL 中的函數
在另一篇博文會描述HIDL 中函數的使用:Android HIDL 中的函數

 

HIDL 的使用
在另一篇博文會詳細描述HelloWorld 在HIDL中的使用:Android HIDL 實例

 

HIDL 生成文件
在編譯HIDL 文件,會在out/soong/.interfaces/PACKAGE/MOUDLE/VERSION/下生成對應的文件。例如Android HIDL 實例 中的helloworld 是在hardware/interfaces下創建,所以生成的文件路徑為:out/soong/.intermediates/hardware/interfaces/helloworld/1.0

 

當然實際生成的文件是根據hidl 對應的Android.bp來的,例如在Android.bp 中設定gen_java_constants為true,會生成一個Constants 的JAVA 類。

android.hardware.helloworld@1.0_genc++_headers 目錄就是為Client 和impl 准備的頭文件。

android.hardware.helloworld@1.0_genc++ 目錄為binder 使用的proxy 和 stub類(或者native 中的Bp 和Bn類)

android.hardware.helloworld-V1.0-java 是為Java 調用生成的java lib

android.hardware.helloworld-V1.0-java_gen_java 是為Java 調用生成的對應的Java 類

詳細信息看博文:Android HIDL 實例
————————————————
版權聲明:本文為CSDN博主「私房菜」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/shift_wwx/java/article/details/86514997


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM