HIDL 程式碼樣式與 Android 架構中的 C++ 程式碼類似,且有 4 個空格 縮排和混合大小寫的檔案名稱。套件宣告、匯入項目和 docstring 與 Java 中的映像檔類似,只是稍做修改。
以下是 IFoo.hal
和 types.hal
的範例
說明 HIDL 程式碼樣式,並提供快速連結,方便您查看每種樣式的詳情
(IFooClientCallback.hal
、IBar.hal
和
已省略 IBaz.hal
)。
hardware/interfaces/foo/1.0/IFoo.hal |
---|
/* * (License Notice) */ package android.hardware.foo@1.0; import android.hardware.bar@1.0::IBar; import IBaz; import IFooClientCallback; /** * IFoo is an interface that… */ interface IFoo { /** * This is a multiline docstring. * * @return result 0 if successful, nonzero otherwise. */ foo() generates (FooStatus result); /** * Restart controller by power cycle. * * @param bar callback interface that… * @return result 0 if successful, nonzero otherwise. */ powerCycle(IBar bar) generates (FooStatus result); /** Single line docstring. */ baz(); /** * The bar function. * * @param clientCallback callback after function is called * @param baz related baz object * @param data input data blob */ bar(IFooClientCallback clientCallback, IBaz baz, FooData data); }; |
hardware/interfaces/foo/1.0/types.hal |
---|
/* * (License Notice) */ package android.hardware.foo@1.0; /** Replied status. */ enum Status : int32_t { OK, /* invalid arguments */ ERR_ARG, /* note, no transport related errors */ ERR_UNKNOWN = -1, }; struct ArgData { int32_t[20] someArray; vec<uint8_t> data; }; |
命名慣例
請使用描述性字詞名稱、變數名稱和檔案名稱;避開
。將縮寫詞視為字詞 (例如,改用 INfc
(共 INFC
個)。
目錄結構和檔案命名
目錄結構應如下所示:
ROOT-DIRECTORY
MODULE
SUBMODULE
(選用,可以是多個值) 等級)VERSION
Android.mk
IINTERFACE_1.hal
IINTERFACE_2.hal
…
IINTERFACE_N.hal
types.hal
(非必要)
地點:
ROOT-DIRECTORY
是:hardware/interfaces
:適用於核心 HIDL 套件。- 針對供應商套裝方案為
vendor/VENDOR/interfaces
, 其中VENDOR
是指 SoC 供應商或 原始設備製造商 (OEM)/ODM。
MODULE
應為以下描述的一個小寫字詞: 子系統 (例如nfc
)。如需輸入多個字詞,請使用 巢狀SUBMODULE
。可以使用多個等級 建立巢狀結構VERSION
應完全相同 (major.minor),詳情請參閱「版本」。IINTERFACE_X
應為含有UpperCamelCase
/PascalCase
(例如INfc
) ,如同「介面名稱」中所述。
例子:
hardware/interfaces
nfc
1.0
Android.mk
INfc.hal
INfcClientCallback.hal
types.hal
注意:所有檔案都必須不是執行檔 權限 (位於 Git 中)
套件名稱
套件名稱必須使用以下完整名稱
(FQN) 格式 (稱為 PACKAGE-NAME
):
PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
地點:
PACKAGE
是對應至ROOT-DIRECTORY
。我們要用PACKAGE
是:- 核心 HIDL 套件的
android.hardware
(對應至以下項目:hardware/interfaces
)。 vendor.VENDOR.hardware
適用於供應商套件,其中VENDOR
是指 SoC 供應商或原始設備製造商 (OEM)/ODM (對應) 至vendor/VENDOR/interfaces
)。
- 核心 HIDL 套件的
MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
是跟先前在語句中所述 目錄結構。- 套件名稱應使用小寫。如果長度超過一個字
字詞應做為子模組或以
snake_case
編寫。 - 不得包含空格。
套件宣告一律使用 FQN。
版本
版本必須採用以下格式:
MAJOR.MINOR
MAJOR 和 MINOR 版本應為單一版本 整數值。HIDL 使用語意 版本管理規則。
匯入
匯入作業有下列三種格式之一:
- 整個套件匯入作業:
import PACKAGE-NAME;
- 部分匯入:
import PACKAGE-NAME::UDT;
(如果已匯入 屬於同一套件、import UDT;
- 僅限類型匯入:
import PACKAGE-NAME::types;
PACKAGE-NAME
會採用以下格式:
套件名稱。目前套件的
types.hal
(如果有的話) 會自動匯入 (請勿匯入)
)。
完整名稱 (FQN)
請只在必要時,才使用完整名稱匯入使用者定義的類型。
如果匯入類型相同,請省略 PACKAGE-NAME
套件。FQN 不得包含空格。完整名稱範例:
android.hardware.nfc@1.0::INfcClientCallback
在 android.hardware.nfc@1.0
的另一個檔案中,參照
視為 INfcClientCallback
否則,請僅使用
完整名稱。
將匯入分組和排序
請在套件宣告之後 (匯入前) 使用空白行。每次匯入 應佔據單行,且不應縮排。將群組匯入 以下順序:
- 其他
android.hardware
套件 (使用完整名稱)。 - 其他
vendor.VENDOR
套件 (使用完整合格套件 名稱)。- 每個供應商都應該為一個群組。
- 按照字母順序訂購供應商。
- 從同一套件中的其他介面匯入 (使用簡單名稱)。
群組之間請使用空白行。在每個群組中,排序匯入項目 。例子:
import android.hardware.nfc@1.0::INfc; import android.hardware.nfc@1.0::INfcClientCallback; /* Importing the whole module. */ import vendor.barvendor.bar@3.1; import vendor.foovendor.foo@2.2::IFooBar; import vendor.foovendor.foo@2.2::IFooFoo; import IBar; import IFoo;
介面名稱
介面名稱的開頭必須是 I
,後接
UpperCamelCase
/PascalCase
名稱。具有名稱的介面
必須在 IFoo.hal
檔案中定義「IFoo
」。這個檔案
只能包含 IFoo
介面 (介面) 的定義
INAME
應為 INAME.hal
)。
函式
針對函式名稱、引數和傳回變數名稱,請採用
lowerCamelCase
。例子:
open(INfcClientCallback clientCallback) generates (int32_t retVal); oneway pingAlive(IFooCallback cb);
結構和聯集欄位名稱
如果是結構體或聯集欄位名稱,請使用 lowerCamelCase
。例子:
struct FooReply { vec<uint8_t> replyData; }
類型名稱
型別名稱是指結構體或聯集定義、列舉類型定義,以及
typedef
秒。這類名稱請使用
UpperCamelCase
/PascalCase
。範例:
enum NfcStatus : int32_t { /*...*/ }; struct NfcData { /*...*/ };
列舉值
列舉值應為 UPPER_CASE_WITH_UNDERSCORES
。通過
以函式引數的形式傳回列舉值,然後傳回這些引數做為函式傳回值,請使用
實際列舉類型 (而非基礎整數類型)。例子:
enum NfcStatus : int32_t { HAL_NFC_STATUS_OK = 0, HAL_NFC_STATUS_FAILED = 1, HAL_NFC_STATUS_ERR_TRANSPORT = 2, HAL_NFC_STATUS_ERR_CMD_TIMEOUT = 3, HAL_NFC_STATUS_REFUSED = 4 };
注意:列舉類型的基礎類型是 。由於不屬於編譯器,方法是使用 實際的列舉類型較為清晰
如果是列舉值的完整名稱,系統會使用半形冒號 是否在列舉類型名稱與列舉值名稱之間:
PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME
完整名稱中不得使用空格。使用完整的 並省略不必要的部分。例子:
android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK
留言
如果是單行註解,則 //
、/* */
和 /** */
沒關係。
// This is a single line comment /* This is also single line comment */ /** This is documentation comment */
-
使用
/* */
留言。雖然 HIDL 支援使用//
註解, 並不會出現在生成的輸出內容中,因此不建議使用。 - 使用
/** */
處理產生的文件。可套用 只有型別、方法、欄位和列舉值宣告。範例:/** Replied status */ enum TeleportStatus { /** Object entirely teleported. */ OK = 0, /** Methods return this if teleportation is not completed. */ ERROR_TELEPORT = 1, /** * Teleportation could not be completed due to an object * obstructing the path. */ ERROR_OBJECT = 2, ... }
- 使用
/**
開始另行註解。 請在每行開頭使用*
。 以*/
做為註解換行,並對齊星號。 範例:/** * My multi-line * comment */
- 授權聲明和變更記錄應以新的一行為
/*
開頭 (單一星號),請在每行開頭使用*
,然後將 最後一行的*/
本身要保留 (星號必須對齊)。 範例:/* * Copyright (C) 2017 The Android Open Source Project * ... */ /* * Changelog: * ... */
檔案中的註解
請在每個檔案的開頭加上適當的授權通知。以核心 HAL 來說
應具備的
development/docs/copyright-templates/c.txt
。
記得更新年份並使用 /* */
樣式的多行註解
如上所述。
您可以選擇在授權通知後方加上空白行,後面再行
並依照變更記錄/版本資訊傳回使用 /* */
樣式
在多行註解中如上所述,在
變更記錄,然後依照套件宣告內容進行處理。
TODO 註解
TODO 應全部以大寫輸入 TODO
字串,後接
冒號。例子:
// TODO: remove this code before foo is checked in.
TODO 留言只能在開發期間獲得。他們必須 並不存在發布的介面中。
介面和函式註解 (文件字串)
使用 /** */
處理多行和單行 docstring。不使用
//
代表 docstring。
介面的 Docstring 應說明 介面、設計理由、用途等。函式的 Docstring 應該 專屬於該函式 (套件層級的說明文件會在 套件目錄)。
/** * IFooController is the controller for foos. */ interface IFooController { /** * Opens the controller. * * @return status HAL_FOO_OK if successful. */ open() generates (FooStatus status); /** Close the controller. */ close(); };
您必須為各個屬性新增 @param
和 @return
參數/回傳值:
- 您必須為每個參數新增
@param
。這應該 後面加上參數的名稱,然後是 docstring。 - 您必須為每個傳回值新增
@return
。這項服務 後面應為傳回值的名稱,然後是 docstring。
例子:
/** * Explain what foo does. * * @param arg1 explain what arg1 is * @param arg2 explain what arg2 is * @return ret1 explain what ret1 is * @return ret2 explain what ret2 is */ foo(T arg1, T arg2) generates (S ret1, S ret2);
格式設定規則
一般格式設定規則包括:
- 線條長度:每一行文字不得超過 長度為 100 欄。
- 空白字元。行上沒有結尾空格;空白行 不得包含空白字元。
- 聊天室與分頁:只能使用空格,
- 縮排大小。使用 4 個空格做為封鎖和 8 個換行空格
- 搞怪。備註除外
值,左大括號與前一行
但「右」大括號和以下半形分號
整個行。範例:
interface INfc { close(); };
套件宣告
授權後,套件宣告應位於檔案頂端 注意,應佔滿整行,而不應縮排套裝內容為 宣告的方式,(如需名稱格式,請參閱 套件名稱):
package PACKAGE-NAME;
例子:
package android.hardware.nfc@1.0;
函式宣告
函式名稱、參數、generates
和傳回值應
可以在同一線了。例子:
interface IFoo { /** ... */ easyMethod(int32_t data) generates (int32_t result); };
如果兩者無法在同一行中,請嘗試加入參數,並傳回
值相同,並且區分 generate
,以協助您
讀取器可快速查看參數和傳回值例子:
interface IFoo { suchALongMethodThatCannotFitInOneLine(int32_t theFirstVeryLongParameter, int32_t anotherVeryLongParameter); anEvenLongerMethodThatCannotFitInOneLine(int32_t theFirstLongParameter, int32_t anotherVeryLongParameter) generates (int32_t theFirstReturnValue, int32_t anotherReturnValue); superSuperSuperSuperSuperSuperSuperLongMethodThatYouWillHateToType( int32_t theFirstVeryLongParameter, // 8 spaces int32_t anotherVeryLongParameter ) generates ( int32_t theFirstReturnValue, int32_t anotherReturnValue ); /* method name is even shorter than 'generates' */ foobar(AReallyReallyLongType aReallyReallyLongParameter, AReallyReallyLongType anotherReallyReallyLongParameter) generates (ASuperLongType aSuperLongReturnValue, // 4 spaces ASuperLongType anotherSuperLongReturnValue); }
其他詳細資料:
- 左括號一律與函式名稱位於同一行。
- 函式名稱與左括號之間沒有空格。
- 括號與參數之間不得有空格,但「除外」 就是兩者之間的換行
- 如果
generates
與前一個關閉時間相同 請使用前面的空格做為括號。如果generates
相同 做為下一個左括號的後方,後接空格。 - 所有參數並保持一致 (如果可以的話)。
- 預設的縮排是 4 個空格。
- 已包裝參數會與上一行的第一個參數對齊。 否則會以 8 空格縮排
註解
註解格式如下:
@annotate(keyword = value, keyword = {value, value, value})
依字母順序排列註解,並在等號前後使用空格。 例子:
@callflow(key = value) @entry @exit
確保註解佔滿整行。例如:
/* Good */ @entry @exit /* Bad */ @entry @exit
如果註解無法容納在同一行,請使用 8 個空格縮排。 例子:
@annotate( keyword = value, keyword = { value, value }, keyword = value)
如果整個值陣列無法在同一行中,請在後面加上換行符號
左大括號 {
,在陣列中每個半形逗號之後。地點已打烊
在最後一個值後面,加上括號。請勿使用大括號
只需要一個值
如果整個值陣列可以在同一行中,請勿在後方使用空格 左大括號和右大括號,且每個逗號後方各有一個空格。 例如:
/* Good */ @callflow(key = {"val", "val"}) /* Bad */ @callflow(key = { "val","val" })
註解和函式之間不得有空白行 宣告內容例如:
/* Good */ @entry foo(); /* Bad */ @entry foo();
列舉宣告
請使用以下列舉宣告規則:
- 如果列舉宣告與其他套件共用,請加入宣告
而不要嵌入介面內。
types.hal
- 冒號前後各須有空格,且基礎類型後方應有空格 。
- 最後一個列舉值可能不包含額外的半形逗號。
結構宣告
請使用以下結構體宣告規則:
- 如果與其他套件共用結構體宣告,請放入宣告
而不要嵌入介面內。
types.hal
- 在結構體類型名稱之後,請在左大括號前加上空格。
- 對齊欄位名稱 (選用)。範例:
struct MyStruct { vec<uint8_t> data; int32_t someInt; }
陣列宣告
請勿在下列項目之間加入空格:
- 元素類型和左方括號。
- 左方括號和陣列大小。
- 陣列大小和右方括號。
- 關閉方括號和下一個左方括號 (如有多個) 維度已存在。
例如:
/* Good */ int32_t[5] array; /* Good */ int32_t[5][6] multiDimArray; /* Bad */ int32_t [ 5 ] [ 6 ] array;
向量
請勿在下列項目之間加入空格:
vec
和左角括號。- 左角括號和元素類型 (例外狀況:元素類型也是
vec
)。 - 元素類型和封閉角括號 (例外狀況:元素類型也是
vec
)。
例如:
/* Good */ vec<int32_t> array; /* Good */ vec<vec<int32_t>> array; /* Good */ vec< vec<int32_t> > array; /* Bad */ vec < int32_t > array; /* Bad */ vec < vec < int32_t > > array;