進行我們的可用性調查以改進此站點。
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

適用於HAL的AIDL

Android 11引入了將AIDL用於HAL的功能。這樣就可以在沒有HIDL的情況下實現Android的某些部分。盡可能地將HAL轉換為僅使用AIDL(當上游HAL使用HIDL時,必須使用HIDL)。

使用AIDL在框架組件(例如system.img組件)和硬件組件(例如vendor.img組件)之間進行通信的HAL必須使用穩定的AIDL。但是,要在一個分區內進行通信(例如從一個HAL到另一個HAL),對使用的IPC機制沒有限制。

動機

AIDL比HIDL更長,並且已在許多其他地方使用,例如在Android框架組件之間或在應用程序中。既然AIDL具有穩定性支持,則可以使用單個IPC運行時實現整個堆棧。 AIDL還具有比HIDL更好的版本控制系統。

  • 使用單一的IPC語言意味著只需要學習,調試,優化和保護一件事。
  • AIDL支持接口所有者的就地版本控制:
    • 所有者可以將方法添加到接口的末尾,也可以將字段添加到可包裹的字段。這意味著多年來對代碼進行版本控制比較容易,並且逐年成本也較小(類型可以就地修改,並且每個接口版本都不需要額外的庫)。
    • 擴展接口可以在運行時附加,而不是在類型系統中附加,因此不需要將下游擴展基於新版本的接口。
  • 當現有AIDL接口的所有者選擇穩定它時,可以直接使用它。在此之前,必須在HIDL中創建接口的完整副本。

編寫AIDL HAL接口

對於要在系統和供應商之間使用的AIDL接口,該接口需要進行兩項更改:

  • 每個類型定義都必須使用@VintfStability進行註釋。
  • aidl_interface聲明需要包含stability: "vintf",

只有接口的所有者才能進行這些更改。

此外,為了最大程度地提高代碼的可移植性並避免潛在的問題(例如不必要的附加庫),請禁用CPP後端。

請注意,在下面的代碼示例中使用backends是正確的,因為有三個後端(Java,NDK和CPP)。下面的代碼告訴您如何具體選擇CPP後端以將其禁用。

    aidl_interface: {
        ...
        backends: {
            cpp: {
                enabled: false,
            },
        },
    }

查找AIDL HAL接口

用於HAL的AOSP穩定AIDL接口與AID aidl夾中的HIDL接口位於相同的基本目錄中。

  • 硬件/接口
  • 框架/硬件/接口
  • 系統/硬件/接口

您應該將擴展接口放入vendorhardware其他hardware/interfaces子目錄中。

擴展接口

Android在每個版本中都有一套官方的AOSP界面。當Android合作夥伴想要向這些接口添加功能時,他們不應直接更改它們,因為這將意味著其Android運行時與AOSP Android運行時不兼容。對於GMS設備,避免更改這些接口也是確保GSI映像可以繼續工作的原因。

擴展可以兩種不同的方式註冊:

  • 在運行時,請參閱附件擴展
  • 獨立的,在全球範圍內和VINTF註冊的。

但是,註冊擴展時,特定於供應商的(意味著不是上游AOSP的一部分)組件使用該接口時,就不可能發生合併衝突。但是,當對上游AOSP組件進行下游修改時,可能會導致合併衝突,因此建議採用以下策略:

  • 在下一個版本中,可以將接口添加項添加到AOSP的上游
  • 在下一版本中,可以上游添加接口接口,以提供更大的靈活性,而不會發生合併衝突。

針對AIDL運行時進行構建

AIDL具有三種不同的後端:Java,NDK,CPP。要使用穩定的AIDL,必須始終在system/lib*/libbinder.so使用libbinder的系統副本,並在/dev/binder上進行交談。對於供應商映像上的代碼,這意味著不能使用libbinder (來自VNDK):該庫具有不穩定的C ++ API和不穩定的內部結構。相反,本機供應商代碼必須使用AIDL的NDK後端,鏈接到libbinder_ndk (由系統libbinder.so支持),並鏈接到aidl_interface條目創建的-ndk_platform庫。

AIDL HAL服務器實例名稱

按照慣例,AIDL HAL服務的實例名稱格式$package.$type/$instance 。例如,振動器HAL的實例註冊為android.hardware.vibrator.IVibrator/default

編寫AIDL HAL服務器

必須在VINTF清單中聲明AIDL服務器,例如:

    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <version>1</version>
        <fqname>IVibrator/default</fqname>
    </hal>

否則,他們應正常註冊AIDL服務。運行VTS測試時,期望所有聲明的AIDL HAL均可用。

編寫一個AIDL客戶端

AIDL客戶端必須在兼容性矩陣中聲明自己,例如:

    <hal format="aidl" optional="true">
        <name>android.hardware.vibrator</name>
        <version>1-2</version>
        <interface>
            <name>IVibrator</name>
            <instance>default</instance>
        </interface>
    </hal>

將現有的HAL從HIDL轉換為AIDL

使用hidl2aidl工具將HIDL接口轉換為AIDL。

hidl2aidl功能:

  • 根據給定包的.hal文件創建.aidl文件
  • 為啟用了所有後端的新創建的AIDL包創建構建規則
  • 在Java,CPP和NDK後端中創建轉換方法,以從HIDL類型轉換為AIDL類型
  • 創建具有所需依賴項的翻譯庫的構建規則
  • 創建靜態斷言以確保HIDL和AIDL枚舉數在CPP和NDK後端中具有相同的值

請按照以下步驟將.hal文件包轉換為.aidl文件:

  1. 構建位於system/tools/hidl/hidl2aidl

    從最新資源構建此工具可提供最完整的體驗。您可以使用最新版本來轉換早期版本中較舊分支上的接口。

    m hidl2aidl
    
  2. 在輸出目錄後執行要轉換的程序包,執行該工具。

    hidl2aidl -o <output directory> <package>
    

    例如:

    hidl2aidl -o . android.hardware.nfc@1.2
    
  3. 通讀生成的文件並解決轉換中的所有問題。

    • conversion.log包含任何未解決的問題,需要首先修復。
    • 生成的.aidl文件可能包含警告和建議,可能需要採取措施。這些註釋以//開頭。
    • 藉此機會清理並改進程序包。
  4. 只建立您需要的目標。

    • 禁用不會使用的後端。 NDK後端優先於CPP後端,請參閱選擇運行時
    • 刪除翻譯庫或其將不使用的任何生成代碼。

AIDL HAL的分隔符

供應商代碼可見的AIDL服務類型必須具有vendor_service屬性。否則,Sepolicy配置與任何其他AIDL服務相同。

    type hal_power_service, service_manager_type, vendor_service;

對於平台定義的大多數服務,已經添加了具有正確類型的服務上下文(例如, android.hardware.power.IPower/default已標記為hal_power_service )。但是,如果框架客戶端支持多個實例名稱,則必須在特定於設備的service_contexts文件中添加其他實例名稱。

    android.hardware.power.IPower/custom_instance u:object_r:hal_power_service:s0

附加的擴展接口

擴展可以附加到任何綁定程序接口,無論它是直接向服務管理器註冊的頂級接口還是子接口。獲取擴展名時,必須確認擴展名的類型符合預期。擴展只能在提供活頁夾的過程中進行設置。

每當擴展修改了現有HAL的功能時,都應使用附加的擴展。如果需要全新的功能,則無需使用此機制,並且可以直接向服務管理器註冊擴展接口。附加的擴展接口在連接到子接口時最有意義,因為這些層次結構可能很深,也可能是多實例的。使用全局擴展來鏡像另一個服務的活頁夾接口層次結構將需要大量的簿記,以提供與直接附加的擴展等效的功能。

要在活頁夾上設置擴展名,請使用以下API:

  • 在NDK後端中: AIBinder_setExtension
  • 在Java後端中: android.os.Binder.setExtension
  • 在CPP後端中: android::Binder::setExtension

要獲取活頁夾的擴展名,請使用以下API:

  • 在NDK後端中: AIBinder_getExtension
  • 在Java後端中: android.os.IBinder.getExtension
  • 在CPP後端中: android::IBinder::getExtension

您可以在相應後端的getExtension函數的文檔中找到有關這些API的更多信息。可以在hardware / interfaces / tests / extension / vibrator中找到如何使用擴展的示例。

主要AIDL / HIDL差異

使用AIDL HAL或使用AIDL HAL接口時,請注意與編寫HIDL HAL相比的區別。

  • AIDL語言的語法更接近Java。 HIDL語法類似於C ++。
  • 所有AIDL接口都有內置的錯誤狀態。在接口文件中創建常量狀態int並在CPP / NDK後端中使用EX_SERVICE_SPECIFIC ,在Java後端中使用ServiceSpecificException ,而不是創建自定義狀態類型。
  • 發送活頁夾對象時,AIDL不會自動啟動線程池。它們必須手動啟動(請參閱線程管理)。
  • AIDL不會因未檢查的傳輸錯誤而中止(HIDL Return因未檢查的錯誤而中止)。
  • AIDL每個文件只能聲明一種類型。
  • 除了輸出參數外,還可以將AIDL參數指定為in / out / inout(沒有“同步回調”)。
  • AIDL使用fd作為原始類型而不是句柄。
  • HIDL使用主要版本進行不兼容的更改,使用次要版本進行兼容的更改。在AIDL中,向後兼容的更改已就位。 AIDL沒有主要版本的明確概念;而是將其合併到程序包名稱中。例如,AIDL可能使用包名稱bluetooth2