創建 HAL 接口

您必須使用 HIDL 來描述用於條件編譯框架的所有建置標誌。相關建構標誌必須分組並包含在單一.hal檔案中。使用 HIDL 指定配置項有以下好處:

  • 版本控制(要新增的配置項,供應商/OEM 必須明確擴充 HAL)
  • 有據可查
  • 使用 SELinux 進行存取控制
  • 透過供應商測試套件對配置項進行健全性檢查(範圍檢查、專案之間的相互依賴性檢查等)
  • 自動產生 C++ 和 Java 版本的 API

識別框架使用的構建標誌

首先確定用於有條件編譯框架的建置配置,然後放棄過時的配置以使集合更小。例如,為surfaceflinger標識了以下一組建置標誌:

  • TARGET_USES_HWC2
  • TARGET_BOARD_PLATFORM
  • TARGET_DISABLE_TRIPLE_BUFFERING
  • TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
  • NUM_FRAMEBUFFER_SURFACE_BUFFERS
  • TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
  • VSYNC_EVENT_PHASE_OFFSET_NS
  • SF_VSYNC_EVENT_PHASE_OFFSET_NS
  • PRESENT_TIME_OFFSET_FROM_VSYNC_NS
  • MAX_VIRTUAL_DISPLAY_DIMENSION

建立 HAL 介面

子系統的建置配置可透過 HAL 介面存取,而用於提供配置值的介面則分組在 HAL 套件android.hardware.configstore中(目前版本為 1.0)。例如,要在hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal中為surfaceflinger建立 HAL 介面檔:

package android.hardware.configstore@1.0;

interface ISurfaceFlingerConfigs {
    // TO-BE-FILLED-BELOW
};

建立.hal檔案後,執行hardware/interfaces/update-makefiles.sh將新的.hal檔案加入Android.bpAndroid.mk檔案。

新增建構標誌的函數

對於每個建置標誌,向介面新增一個函數。例如,在hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal

interface ISurfaceFlingerConfigs {
    disableTripleBuffering() generates(OptionalBool ret);
    forceHwcForVirtualDisplays() generates(OptionalBool ret);
    enum NumBuffers: uint8_t {
        USE_DEFAULT = 0,
        TWO = 2,
        THREE = 3,
    };
    numFramebufferSurfaceBuffers() generates(NumBuffers ret);
    runWithoutSyncFramework() generates(OptionalBool ret);
    vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret);
    presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret);
    maxVirtualDisplayDimension() generates(OptionalInt32 ret);
};

新增函數時:

  • 名稱要簡潔。避免將 makefile 變數名轉換為函數名,並記住不再需要TARGET_BOARD_前綴。
  • 新增評論。幫助開發人員了解配置項目的用途、它如何更改框架行為、有效值以及其他相關資訊。

函數傳回型別可以是Optional[Bool|String|Int32|UInt32|Int64|UInt64] 。類型在同一目錄中的types.hal中定義,並用一個欄位包裝原始值,該欄位指示該值是否由 HAL 指定;如果沒有,則使用預設值。

struct OptionalString {
    bool specified;
    string value;
};

在適當的時候,定義最能代表配置項目類型的枚舉,並使用該枚舉作為返回類型。在上面的範例中,定義NumBuffers枚舉來限制有效值的數量。定義此類自訂資料類型時,請新增欄位或枚舉值(例如USE_DEFAULT )以指示該值是否由 HAL 指定。

單一建置標誌不必成為 HIDL 中的單一函數。模組擁有者也可以將密切相關的建置標誌聚合到一個結構中,並擁有一個傳回該結構的函數(這樣做可以減少函數呼叫的數量)。

例如,將兩個建置標誌聚合到hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal中的單一結構中的選項是:

 interface ISurfaceFlingerConfigs {
    // other functions here
    struct SyncConfigs {
        OptionalInt64 vsyncEventPhaseoffsetNs;
        OptionalInt64 presentTimeoffsetFromSyncNs;
    };
    getSyncConfigs() generates (SyncConfigs ret);
    // other functions here
};

單一 HAL 函數的替代方案

作為對所有建置標誌使用單一 HAL 函數的替代方法,HAL 介面還提供簡單的函數,例如getBoolean(string key)getInteger(string key) 。實際的key=value對儲存在單獨的檔案中,HAL 服務透過讀取/解析這些檔案來提供值。

雖然這種方法很容易定義,但它不包括 HIDL 提供的好處(強製版本控制、易於文件化、存取控制),因此不建議。

單一和多個介面

配置項的HAL介面的設計提出了兩種選擇:

  • 單一介面涵蓋所有配置項
  • 多個接口,每個接口涵蓋一組相關的配置項

單一介面更容易,但隨著更多配置項添加到單一檔案中,可能會變得難以維護。此外,存取控制不是細粒度的,因此被授予介面存取權限的程序可以讀取所有配置項目(無法授予對部分配置項集的存取權限)。或者,如果未授予存取權限,則無法讀取設定項。

由於這些問題,Android 使用多個介面和單一 HAL 介面來處理一組相關的設定項。例如surfaceflinger相關的配置項目為ISurfaceflingerConfigs ,藍牙相關的配置項目為IBluetoothConfigs