HIDL 框架向後兼容性驗證

HIDL HAL保證 Android 核心系統(又名 system.img 或框架)向後兼容。雖然供應商測試套件 (VTS)測試確保 HAL 按預期工作(例如,在所有 1.2 實現上運行 1.1 HAL 測試),但需要框架測試以確保在提供受支持的 HAL(1.0、1.1 或 1.2)時,框架與該 HAL 正常工作。

有關 HAL 接口定義語言 (HIDL) 的詳細信息,請參閱HIDLHIDL 版本控制HIDL HAL 棄用

關於 HAL 升級

HAL 升級有兩種類型:主要次要。大多數係統僅包含一種 HAL 實現,但支持多種實現。例如:

android.hardware.teleport@1.0 # initial interface
android.hardware.teleport@1.1 # minor version upgrade
android.hardware.teleport@1.2 # another minor version upgrade
...
android.hardware.teleport@2.0 # major version upgrade
...

系統分區通常包括一個框架守護進程(例如teleportd ),它管理與一組特定 HAL 實現的通信。或者,系統可能包含一個實現方便客戶端行為的系統庫(例如android.hardware.configstore-utils )。在上面的示例中,無論設備上安裝什麼版本的 HAL, teleportd都必須工作。

Google 維護的版本

如果存在主要版本升級(1.0、2.0、3.0 等),則至少有一台由 Google 維護的設備必須維護每個主要版本的實現,直到該版本被棄用。如果 Google 維護的設備未附帶特定的主要版本,Google 將繼續維護該主要版本的舊實現。

這樣的維護會增加少量的額外開銷,因為在創建新實現(例如 2.0)時,可以保留舊實現(例如 1.2)並且默認情況下不使用。

測試次要版本升級

在框架中測試次要版本的向後兼容性需要一種自動生成次要版本實現的方法。鑑於圍繞 Google 維護的版本的限制, hidl-gen將僅(並且只能)生成採用 1.(x+n) 實現並提供 1.x 實現的適配器;它不能從 2.0 實現(根據主要版本的定義)生成 1.0 實現。

例如,要在 1.2 實現上運行 1.1 測試,您必須能夠模擬 1.1 實現。 1.2 接口可以自動用作 1.1 實現,但在行為上有一些細微差別(例如框架手動檢查某物是什麼版本或在其上調用castFrom )。

基本思想是這樣的:

  1. 在 Android 移動設備上安裝 x.(y+n) 接口。
  2. 安裝並激活 xy 目標適配器。
  3. 測試設備以驗證它在運行較舊的次要版本時是否按預期工作。

這些適配器完全隱藏了實現實際上由 1.2 接口支持並且僅提供 1.1 接口的事實(適配器採用 1.2 接口並使其看起來像 1.1 接口)。

示例工作流程

在此示例中,Android 設備運行android.hardware.foo@1.1::IFoo/default 。為確保客戶端與android.hardware.foo@1.0::IFoo/default一起正常工作:

  1. 在終端中,運行以下命令:
    $ PACKAGE=android.hidl.allocator@1.0-adapter
    $ INTERFACE=IAllocator
    $ INSTANCE=ashmem
    $ THREAD_COUNT=1 # can see current thread use on `lshal -i -e`
    $ m -j $PACKAGE
    $ /data/nativetest64/$PACKAGE/$PACKAGE $INTERFACE $INSTANCE $THREAD_COUNT
    Trying to adapt down android.hidl.allocator@1.0-adapter/default
    Press any key to disassociate adapter.
  2. 使用adb shell stop (或start )重新啟動客戶端或簡單地終止該進程。
  3. 測試完成後,解除與適配器的關聯。
  4. 通過重新啟動設備或通過重新啟動客戶端來恢復系統狀態。

其他目標

hidl-gen自動為構建系統中使用hidl_interface指定的每個接口的適配器添加額外的構建目標。對於包abc@xy ,還有一個額外的 C++ 目標abc@xy-adapter

abc@xy的適配器將某些實現abc@x.(y+n)::ISomething/instance-name作為輸入,並且必須註冊abc@xy::ISomething/instance-name ,它還必須取消註冊y+n實施。

給定以下示例界面:

// IFoo.hal
package a.b.c@1.0;
interface IFoo {
    doFoo(int32_t a) generates (int64_t b);
    doSubInterface() generates (IFoo a);
};

abc@1.0-adapter提供的代碼類似於下面的示例:

// autogenerated code
// in namespace a::b::c::V1_0::IFoo
struct MockFoo {
    // takes some subclass of V1_0. May be V1_1, V1_2, etc...
    MockFoo(V1_0::IFoo impl) mImpl(impl) {}

    Return<int64_t> doFoo(int32_t a) {
        return this->mImpl->doFoo(a);
    }

    Return<V1_0::ICallback> doSubInterface() {
        // getMockForBinder returns MockCallback instance
        // that corresponds to a particular binder object
        // It can't return a new object every time or
        // clients using interfacesSame will have
        // divergent behavior when using the mock.
        auto _hidl_out = this->mImpl->doSubInterface();
        return getMockForBinder(_hidl_out);
    }
};

數據值準確地進出自動生成的模擬類,返回的子接口除外。這些接口必須包裝在相應的最新回調對像中。