Android 11 には、HAL 用の AIDL を使用するための機能が導入されています。このため、Android の一部を HIDL なしで実装することができます。 可能であれば、AIDL のみを使用するように HAL を変更することを強くおすすめします(アップストリームの HAL で HIDL を使用する場合は、HIDL を使用する必要があります)。
フレームワーク コンポーネント(system.img
内のフレームワーク コンポーネントなど)とハードウェア コンポーネント(vendor.img
内のハードウェア コンポーネントなど)間の通信に AIDL を使用する HAL では、安定版 AIDL を使用する必要があります。ただし、パーティション内で通信する場合(HAL 間の通信など)、使用する IPC メカニズムに関する制限はありません。
AIDL の利点
AIDL は HIDL よりも古くから存在し、Android フレームワーク コンポーネント間やアプリ内など、さまざまな場面で使用されています。現在、AIDL は安定性もサポートされるようになっており、単一の IPC ランタイムでスタック全体を実装できます。また、AIDL のバージョニング システムは HIDL より優れています。
- 単一の IPC 言語を使用するため、学習、デバッグ、最適化、保護の対象に必要なものも 1 つだけです。
- AIDL は、インターフェースのオーナー向けにインプレースのバージョニングをサポートしています。
- オーナーは、インターフェースの最後にメソッドを追加したり、Parcelable にフィールドを追加したりできます。 つまり、コードのバージョニングを長年にわたって簡単に行うことができるうえ、そのコストを年々減らしていくことができます(型をインプレースで修正できるため、インターフェースのバージョンごとにライブラリを追加する必要がありません)。
- 拡張機能のインターフェースの接続は型システムで行われるのではなく、ランタイムに行われるため、ダウンストリームの拡張機能を新しいバージョンのインターフェースにリベースする必要はありません。
- 既存の AIDL インターフェースは、オーナーが固定することを選択した場合、直接使用できます。以前は、インターフェースのコピー全体を HIDL で作成する必要がありました。
AIDL HAL インターフェースの作成
AIDL インターフェースをシステムとベンダー間で使用する場合、インターフェースで次の 2 点を変更する必要があります。
- すべての型定義に
@VintfStability
アノテーションを付ける必要があります。 aidl_interface
の宣言にstability: "vintf",
を含める必要があります。
これらの変更を行えるのはインターフェースのオーナーだけです。
さらに、コードの移植性を最大限に高め、不要な追加ライブラリなどの潜在的な問題を回避するには、CPP バックエンドを無効にすることをおすすめします。
aidl_interface: {
...
backends: {
cpp: {
enabled: false,
},
},
}
AIDL HAL インターフェースの場所
HAL 用の AOSP 安定版 AIDL インターフェースは、HIDL インターフェースと同じベース ディレクトリ(aidl
フォルダ内)にあります。
- hardware/interfaces
- frameworks/hardware/interfaces
- system/hardware/interfaces
拡張機能のインターフェースは vendor
または hardware
内の別の hardware/interfaces
サブディレクトリに配置する必要があります。すべてのデバイス間でインターフェースの整合性をとることを強くおすすめします。拡張機能は次の 2 つの方法で登録できます。
- ランタイムに登録(接続済みの拡張機能のインターフェースをご覧ください)
- スタンドアロンで、グローバルに VINTF に登録
AIDL ランタイムに対するビルド
AIDL には 3 つのバックエンド(Java、NDK、CPP)があります。安定版 AIDL を使用するには、常に libbinder(system/lib*/libbinder.so
)のシステムコピーを使用し、/dev/binder
で通信を行う必要があります。これは、ベンダー イメージのコードでは(VNDK の)libbinder
を使用できないことを意味します(このライブラリは C++ API および内部動作が不安定なため)。その代わり、ネイティブ ベンダーコードで AIDL の NDK バックエンドを使用し、システムの libbinder.so
に支えられた libbinder_ndk
にリンクして、aidl_interface
エントリによって作成された -ndk_platform
ライブラリにリンクする必要があります。
AIDL HAL サーバーのインスタンス名
慣例により、AIDL HAL サービスのインスタンス名には $package.$type/$instance
という形式が使用されています。たとえば、vibrator HAL のインスタンスは android.hardware.vibrator.IVibrator/default
という名前で登録されます。
AIDL HAL サーバーの作成
AIDL サーバーは VINTF マニフェストで宣言する必要があります。次に例を示します。
<hal format="aidl">
<name>android.hardware.vibrator</name>
<fqname>IVibrator/default</fqname>
</hal>
他の点では、AIDL サーバーは AIDL サービスを通常どおりに登録する必要があります。VTS テストの実行時には、宣言されているすべての AIDL HAL を使用できることが期待されます。
AIDL クライアントの作成
AIDL クライアントは互換性マトリックス内で自身を宣言する必要があります。次に例を示します。
<name>android.hardware.vibrator</name>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
既存の HAL を HIDL から AIDL に変換する
HIDL インターフェースを AIDL に変換するには、hidl2aidl
ツールを使用します。
.hal ファイルのパッケージを .aidl ファイルに変換する手順は次のとおりです。
system/tools/hidl/hidl2aidl
にあるツールをビルドします。m hidl2aidl
出力ディレクトリの後に変換するパッケージを指定して、ツールを実行します。
hidl2aidl -o <output directory> <package>
次に例を示します。
hidl2aidl -o . android.hardware.nfc@1.2
生成されたファイルを最初から最後まで確認し、変換によって生じた問題を修正します。
conversion.log
には、最初に修正する必要がある未処理の問題が含まれています。- 生成された
.aidl
ファイルに、対処が必要な警告と提案が含まれていることがあります。それらのコメントは//
で始まります。 - 機会があればパッケージをクリーンアップして改善します。
AIDL HAL 用 sepolicy
ベンダーコードから参照できる 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
上記の API について詳しくは、対応するバックエンドの getExtension
関数のドキュメントをご覧ください。拡張機能の使用例については、hardware/interfaces/tests/extension/vibrator をご覧ください。
AIDL と HIDL の主な違い
AIDL HAL または AIDL HAL インターフェースを使用する際には、HIDL HAL と作成方法が異なることに注意してください。
- AIDL の構文は Java に似ており、HIDL の構文は C++ に似ています。
- すべての AIDL インターフェースにはエラー ステータスが組み込まれています。カスタムのステータス タイプを作成する代わりに、インターフェース ファイルに整数の定数ステータスを作成します。CPP および NDK バックエンドでは
EX_SERVICE_SPECIFIC
を使用し、Java バックエンドではServiceSpecificException
を使用します。 - AIDL では未確認のトランスポート エラーが発生してもプロセスが中止されません(HIDL の
Return
では未確認のエラーが発生した場合、プロセスが中止されます)。 - AIDL では、ファイルごとに 1 つの型のみを宣言できます。
- AIDL の引数は、出力パラメータとして指定できるほか、入力 / 出力 / 入出力として指定することもできます(「同期コールバック」は行われません)。
- AIDL では、fd をハンドルではなくプリミティブ型として使用します。
- HIDL では、互換性のない変更にはメジャー バージョンを使用し、互換性のある変更にはマイナー バージョンを使用します。AIDL では、下位互換性のある変更が行われます。AIDL にはメジャー バージョンの明示的な概念はなく、パッケージ名に組み込まれます。たとえば、AIDL ではパッケージ名
bluetooth2
が使用されることがあります。