学习 Android O HIDL
HIDL 簡介
HIDL 即HAL interface definition language,在 Android Project Treble 中被起草,在 Android O 中被全面使用。
HIDL用于進程間通信(IPC)。對于c++和Java程序員來說,HIDL的語法看起來會很熟悉,即使它有一系列不同的關(guān)鍵字。HIDL還使用java風(fēng)格的注解。
Project Treble
Project treble是Android O中引入的特性.?
主要的目標(biāo)是Android模塊化,根據(jù)谷歌、SoC供應(yīng)商和OEM的需求分離所有權(quán)和分配不同的模塊。?
Vendor 模塊被分離到一個獨立的可單獨更新的image,從而改進了軟件升級發(fā)布的過程?
Treble由以下幾部分組成:
-
Kernel modularization
-
HAL re-architecture (binderization)
-
Separation of the vendor and OEM modules from the system image
關(guān)于HIDL的設(shè)計
HIDL的設(shè)計目的是為了能夠在不重新編譯HALs的情況下能夠替換framework。HALs將由供應(yīng)商或SOC制造商構(gòu)建,并放在設(shè)備的vendor下的分區(qū)中,而framework框架在它自己的分區(qū)中發(fā)揮作用,能夠被OTA替換而不重新編譯HALs。
HIDL的設(shè)計平衡了以下問題:?
共用性?
在進程間創(chuàng)建可靠的共用接口,而這些進程可能有不同的架構(gòu)、工具鏈和構(gòu)建配置。HIDL接口是版本化的,在發(fā)布后不能更改。?
效率?
HIDL會將復(fù)制的次數(shù)最小化。HIDL定義的數(shù)據(jù)以C++標(biāo)準(zhǔn)layout data structures的形式傳遞給c++代碼,這種數(shù)據(jù)結(jié)構(gòu)可以不打包的情況下使用。HIDL還提供共享內(nèi)存接口,由于RPCs天生有點慢,HIDL無需使用RPC調(diào)用,而支持兩種傳輸數(shù)據(jù)的方法:shared memory?(共享內(nèi)存)和?Fast Message Queue?(FMQ).
直觀?
對于RPC,HIDL只使用參數(shù)(參見AIDL),避免了內(nèi)存所有權(quán)的棘手問題;不能有效通過方法返回的值通過回調(diào)函數(shù)返回。既不將數(shù)據(jù)傳遞到HIDL,也不從HIDL接收數(shù)據(jù),改變數(shù)據(jù)的所有權(quán)。數(shù)據(jù)只需要在被調(diào)用函數(shù)的持續(xù)時間內(nèi)存在,并且可以在被調(diào)用函數(shù)返回后立即銷毀。
使用 passthrough 模式
為了更新運行在Android系統(tǒng)早期版本的設(shè)備到Android O操作系統(tǒng),你可以將傳統(tǒng)的(和 legacy遺留的)HALs封裝在新的HIDL接口中,這一接口以binderized 和same-process (passthrough)的模式服務(wù)于HAL。這種封裝對HAL和Android框架都是透明的。
Passthrough模式僅適用于c++的客戶端和實現(xiàn)。運行Android早期版本的設(shè)備沒有Java編寫的HALs,因此Java HALs必然使用binderized 的模式。
Passthrough header files
當(dāng)一個.hal文件被編譯后, hidl-gen除了用于binder通信的頭文件外,還生成一個額外的 passthrough 頭文件 BsFoo.h ;這個頭文件定義了dlopened的函數(shù). 由于passthrough HALs 運行在調(diào)用它們的相同的進程中,大多數(shù)情況下 passthrough 方法被直接通過函數(shù)調(diào)用 (相同線程)。oneway 方法在他們自己的線程中運行,因為它們并不打算等待HAL來處理它們(這意味著任何在passthrough模式中使用oneway方法的HAL必須是線程安全的)。
給定一個IFoo.hal文件,BsFoo.h封裝了hidl生成的方法以提供額外的特性(比如在另一個線程中運行oneway事務(wù))。這個文件類似于BpFoo。但是,不是通過binder進行IPC調(diào)用,而是直接調(diào)用所需的函數(shù)。未來HALs可能提供多種實現(xiàn),例如FooFast HAL和FooAccurate HAL。在這種情況下,將創(chuàng)建每個額外實現(xiàn)的文件(例如:PTFooFast.cpp和PTFooAccurate.cpp)。
Binderizing passthrough HALs
支持passthrough 模式的HAL實現(xiàn)可以binderized 。對于一個HAL 接口a.b.c.d@M.N::IFoo,需要創(chuàng)建兩個包:
- a.b.c.d@M.N::IFoo-impl.?包含HAL的實現(xiàn),并暴露函數(shù)IFoo * HIDL_FETCH_IFoo(const char * name)。在legacy hal設(shè)備上,這個包是dlopened 的,實現(xiàn)是使用HIDL_FETCH_IFoo實例化的。 您可以使用hidl - gen和- lc + + - impl和- landroidbp - impl生成基本代碼。
- a.b.c.d@M.N::IFoo-service.?打開passthrough HAL并將其注冊為一個binder化服務(wù),使相同的HAL實現(xiàn)被用作passthrough 和binderized。
給定類型IFoo,您可以調(diào)用sp < IFoo > IFoo::getService(string name, bool getStub)來獲取IFoo的實例。
如果getStub值是true,getService嘗試只以passthrough模式打開HAL。如果getStub為false,則getService嘗試查找到一個binderized 服務(wù);如果失敗,則嘗試找到passthrough服務(wù)。getStub參數(shù)除了defaultPassthroughServiceImplementation不應(yīng)使用。(使用Android O的設(shè)備是完全binderized 的設(shè)備,因此不允許以passthrough模式打開一個服務(wù)。)
HIDL 語法
HIDL語言類似于C(但不使用C預(yù)處理器)
- /*?/ 表示文檔注釋.
- /* */ 表示文檔多行注釋.
- // 表示在一行結(jié)束后注釋
- [empty] 表明當(dāng)前項的值為空
- ? 放置在項前,表明該項為可選項.
- … 表明該序列包含0個或多個如前述使用分隔符隔開的項
- , 逗號用于分隔序列中的元素
- ; 分號用于標(biāo)記每個元素的結(jié)束位置.
- @entry 當(dāng)前HAL模塊被使用時應(yīng)當(dāng)被最先調(diào)用的接口
- @exit 當(dāng)前HAL模塊被調(diào)用時應(yīng)當(dāng)被最后調(diào)用的接口
- @callflow(next={“name_a”, “name_b”, “name_c”}) 當(dāng)前接口被調(diào)用后可能被調(diào)用的接口列表。其中name_a接口被調(diào)用的概率最大,name_c接口被調(diào)用的概率最小。如果只存在1個可能被調(diào)用的接口,那么花括號{ }可以省略不寫。如果給定的接口名無效,則會導(dǎo)致VTS編譯失敗。
- @callflow(next={“*”}) 當(dāng)前接口被調(diào)用后可能會調(diào)用任意接口
Example:
ROOT =PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... } // not for types.halPREAMBLE = interface identifier EXTENDS| PACKAGE IMPORTS ITEM ITEM... // only for types.hal; no method definitionsITEM =ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;| 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 EXTENDSEXTENDS = <empty> | extends import_name // must be interface, not packageGENERATES = 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 have been previously typedef'd// or defined with struct, union, enum, or import | memory | pointer | vec<TYPE> | bitfield<TYPE> // TYPE is user-defined enum | fmq_sync<TYPE> | fmq_unsync<TYPE> | TYPE[SIZE]FIELD =TYPE identifierUFIELD =TYPE identifier| struct identifier { FIELD; FIELD; ...} identifier;| union identifier { FIELD; FIELD; ...} identifier;SFIELD =TYPE identifier| struct identifier { FIELD; FIELD; ...};| union identifier { FIELD; FIELD; ...};| struct identifier { FIELD; FIELD; ...} identifier;| union identifier { FIELD; FIELD; ...} identifier;SIZE = // Must be greater than zeroconstexprANNOTATIONS =[empty]| ANNOTATIONS ANNOTATIONANNOTATION =| @identifier| @identifier(VALUE)| @identifier(ANNO_ENTRY, ANNO_ENTRY ...)ANNO_ENTRY =identifier=VALUEVALUE ="any text including \" and other escapes"| constexpr| {VALUE, VALUE ...} // only in annotationsENUM_ENTRY =identifier| identifier = constexpr- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
原文地址: http://blog.csdn.net/ch853199769/article/details/77840099
總結(jié)
以上是生活随笔為你收集整理的学习 Android O HIDL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解Linux内存管理--目录导航
- 下一篇: Android Treble架构解析