HAL は、ハードウェア ベンダーが実装する標準インターフェースを定義することで、下位レベルのドライバ実装に Android が依存しないようにするものです。HAL を使用すると、上位レベルのシステムに影響や変更を加えることなく、機能を実装できます。このページでは、以前のアーキテクチャについて説明します。このアーキテクチャは Android 8.0 ではサポートされなくなりました。Android 8.0 以上については、HAL の概要をご覧ください。
図 1. HAL コンポーネント
プロダクトが特定のハードウェアを提供する場合、それに対応する HAL(およびドライバ)を実装する必要があります。HAL 実装は通常、共有ライブラリ モジュール(.so ファイル)に組み込まれますが、HAL 実装とデバイス ドライバ間の標準的な通信は必須ではありません。状況に合わせて実装できます。ただし、Android システムがハードウェアと正しく通信できるようにするには、各ハードウェア固有の HAL インターフェースで定義されているコントラクトを遵守する必要があります。
HAL が予測可能な構造となるように、各ハードウェア固有の HAL インターフェースには hardware/libhardware/include/hardware/hardware.h に定義されたプロパティがあります。このインターフェースにより、Android システムは正しいバージョンの HAL モジュールを一貫した方法で読み込むことができます。HAL インターフェースには、モジュールとデバイスの 2 つのコンポーネントがあります。
HAL モジュール
1 つのモジューがパッケージ化された HAL 実装を表し、共有ライブラリ(.so file)として保存されます。hardware/libhardware/include/hardware/hardware.h ヘッダー ファイルで、モジュールを表す構造体(hw_module_t)を定義し、モジュールのバージョン、名前、作成者などのメタデータを指定します。Android は、このメタデータを使用して、HAL モジュールを正しく検出して読み込みます。
さらに、hw_module_t 構造体には、モジュールのオープン関数へのポインタを含む別の構造体 hw_module_methods_t へのポインタが含まれます。このオープン関数を使用してハードウェアとの通信を開始し、HAL はそのアブストラクションとして機能します。各ハードウェア固有の HAL は通常、汎用 hw_module_t 構造体を拡張して、ハードウェア固有の部分に関する追加情報を含めます。たとえば、カメラ HAL では camera_module_t 構造体に、hw_module_t 構造体とそれ以外のカメラ固有の関数へのポインタが含まれます。
typedef struct camera_module {
hw_module_t common;
int (*get_number_of_cameras)(void);
int (*get_camera_info)(int camera_id, struct camera_info *info);
} camera_module_t;
HAL を実装し、モジュール構造体を作成する際、そのモジュールに HAL_MODULE_INFO_SYM という名前を付けます。以下に Nexus 9 オーディオ HAL の例を示します。
struct audio_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = AUDIO_MODULE_API_VERSION_0_1,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = AUDIO_HARDWARE_MODULE_ID,
.name = "NVIDIA Tegra Audio HAL",
.author = "The Android Open Source Project",
.methods = &hal_module_methods,
},
};
HAL デバイス
デバイスは、プロダクトのハードウェアを抽象化します。たとえば、オーディオ モジュールには、プライマリ オーディオ デバイス、USB オーディオ デバイス、または Bluetooth A2DP オーディオ デバイスを含めることができます。
デバイスは hw_device_t 構造体で表されます。モジュールと同様に、デバイスの各タイプについて、汎用の hw_device_t の詳細バージョンを定義し、そのハードウェアに固有の機能の関数ポインタを含めます。たとえば、audio_hw_device_t 構造体タイプには、オーディオ デバイスのオペレーションへの関数ポインタが含まれます。
struct audio_hw_device {
struct hw_device_t common;
/**
* used by audio flinger to enumerate what devices are supported by
* each audio_hw_device implementation.
*
* Return value is a bitmask of 1 or more values of audio_devices_t
*/
uint32_t (*get_supported_devices)(const struct audio_hw_device *dev);
...
};
typedef struct audio_hw_device audio_hw_device_t;
これらの標準プロパティに加えて、各ハードウェア固有の HAL インターフェースで独自の機能や要件を定義することもできます。詳細については、各 HAL ごとの手順と、HAL リファレンス ドキュメントをご覧ください。
HAL モジュールの作成
HAL 実装はモジュール(.so)ファイルに組み込まれ、必要に応じて Android により動的にリンクされます。HAL 実装ごとに Android.mk ファイルを作成し、ソースファイルを指定することで、モジュールを作成できます。通常、共有ライブラリは正しく検出され読み込まれるように、特定の形式で命名する必要があります。命名方法はモジュールごとに多少異なりますが、<module_type>.<device_name> の一般的なパターンに従います。