従来型 HAL

HAL は、ハードウェア ベンダーが実装する標準インターフェースを定義することで、下位レベルのドライバ実装に Android が依存しないようにするものです。HAL を使用すると、上位レベルのシステムに影響や変更を加えることなく、機能を実装できます。このページでは、以前のアーキテクチャについて説明します。このアーキテクチャは Android 8.0 ではサポートされなくなりました。Android 8.0 以上については、HAL の概要をご覧ください。

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> の一般的なパターンに従います。

レガシー HAL

レガシー HAL とは、Android 8.0 以前のすべての HAL(Android 8 でサポート終了)を指す、汎用的な用語です。Android システム インターフェースの大部分(カメラ、オーディオ、センサーなど)は hardware/libhardware/include/hardware で定義されており、大まかなバージョニングとほぼ安定した ABI を備えています。一部のサブシステム(Wi-Fi、無線インターフェース レイヤ、Bluetooth など)では、その他の標準化されていないインターフェースが libhardware_legacy に含まれていたり、コードベース全体に散在していたりします。レガシー HAL は強固な安定性を保証するものではありませんでした。