従来型 HAL

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 モジュール

モジュールとはパッケージ化された 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> の一般的なパターンに従います。