Android HALモジュール実装

15254 ワード

1.HAL紹介
AndroidのHAL(Hardware Abstract Layerハードウェア抽象層)は、linuxのGPL束縛を避けるために、いくつかのハードウェアプロバイダの知的財産権を保護するために提案されています.ハードウェアを制御する動作をAndroid HALに配置することを考えていますが、linux driverは簡単なデータインタラクションを完了し、ハードウェアレジスタ空間をuser spaceに直接マッピングすることもできます.AndroidはAparchベースのlicenseなので、ハードウェアメーカーはバイナリコードしか提供できないので、Androidはオープンなプラットフォームであり、オープンソースのプラットフォームではありません.
まとめてみると、Android HALが存在する理由は主に以下の通りです.
  • すべてのハードウェアデバイスに標準linux kernelのインタフェースがあるわけではありません
  • KERNEL DRIVERはGPLの著作権に関連している.一部のデバイスメーカーは、ハードウェアドライバを公開する理由がないため、HAL方式でGPLを迂回する.
  • いくつかのハードウェアに対して、Androidにはいくつかの特別なニーズがあります.
  • 異なるプラットフォームメーカーはHAL呼び出しインタフェースに従う前提の下で自分のHALを実現することができて、上層の呼び出し者に影響しないで、このようにモジュール間の結合度を下げて、プラットフォーム開発者にHAL自身の実現だけに関心を持つことができます.

  • 次の図は、androidシステムにおけるHALの位置です.
    この図から,HALはカーネルとframeworkを分離し,上位層の開発をカーネルと駆動の実現に依存させないことが分かる.Androidソースコードでは、HALはほぼ次の位置にあります.
  • libhardware_legacy/-古いアーキテクチャ、リンクライブラリモジュールのモードで行います.
  • libhardware/-新しいアーキテクチャ、HAL stubに調整された概念.
  • ril/- Radio Interface Layer.
  • msm 7 k QUALプラットフォーム関連.

  • 主にGps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Grallocなどのモジュールが含まれています.
    2.HALの二つの実現方式
    次の図は、古いHAL実装と新しいHAL実装のブロック図です.
    libhardware_legacyは*.soファイルはshared libraryとして使用され、runtime(JNI部分)ではdirect function callでHAL moduleが使用されます.直接関数呼び出しでドライバを操作します.もちろん、アプリケーションはJNIで行う必要がなく、直接*をロードすることも可能である.so(dlopen)のやり方呼び出し*.soの中の記号(symbol)も一つの方法です.要するに、パッケージされていないため、上層部はハードウェアを直接操作することができます.
    今のlibhardwareの作り方は、「stub」の味がします.HAL stubはエージェント(proxy)の概念であり、stubは*.soファイルの形式は存在するが、HALはすでに*.soファイルが隠れています.StubはHALに操作関数(operations)を「提供」し,runtimeはHALに特定モジュール(stub)のoperationsを取得し,callbackといった操作関数を持つ.このindirect function callの実作アーキテクチャは、HAL stubを「含む」関係に変え、HALには多くのstub(エージェント)が含まれている.Runtimeは「タイプ」であるmodule IDを説明すれば操作関数を取得できる.現在のHALについては,AndroidがHAL層構造フレームワークを定義し,いくつかのインタフェースを介してハードウェアにアクセスすることで呼び出し方式を統一していると考えられる.
    以上から、この2つの実現方式の優劣が大まかに見られる.
    HAL_legacy方式のHALは、共有ライブラリ形式でコンパイル時に呼び出されるモジュールです.function call形式で呼び出されるため、複数のプロセスで使用できますが、mappingによって複数のプロセス空間に移行し、無駄になります.コードが安全に再入力できるかどうかの問題も考慮する必要があります(thread safe).新しいHALはHAL moduleとHAL stubの結合形式を採用しており、HAL stubはshare libraryではなく、コンパイル時に上層部はHAL stubにアクセスする関数ポインタしか持っておらず、HAL stubは必要ありません.上層部はHAL moduleが提供する統一インタフェースを通じてHAL stubを取得して操作し、soファイルは1つのプロセスにmappingされるだけで、mappingと再読み込みの問題もありません.
    3.HALモジュールの構造と作成方法
    HALモジュールには主に2つの構造があります.
    struct hw_module_t-は抽象ハードウェアモジュールを表し、バージョン番号、開発者など、ハードウェアモジュールの基本情報、メンバー関数構造体などを含む.
    struct hw_module_methods_t,中には抽象ハードウェアデバイスhwを開くための1つしかありませんdevice_tのopen関数ポインタ.
    struct hw_device_t-は抽象的なハードウェアデバイスを表し、バージョン番号、ハードウェアを閉じるclose関数ポインタ、およびhw_を指すmodule_tの構造のポインタ.
    この2つの構造の定義はhardware/libhardware/include/hardware/hardware.hでは、自分のhw moduleとhw device構造を実現する際に、最初のメンバー変数は、C++の継承のような目的を達成するために、この2つの構造でなければならない.
    この2つの構造の定義は次のとおりです.
    typedef struct hw_module_t {
        /** tag must be initialized to HARDWARE_MODULE_TAG */
        uint32_t tag;
    
        /**
         * The API version of the implemented module. The module owner is
         * responsible for updating the version when a module interface has
         * changed.
         *
         * The derived modules such as gralloc and audio own and manage this field.
         * The module user must interpret the version field to decide whether or
         * not to inter-operate with the supplied module implementation.
         * For example, SurfaceFlinger is responsible for making sure that
         * it knows how to manage different versions of the gralloc-module API,
         * and AudioFlinger must know how to do the same for audio-module API.
         *
         * The module API version should include a major and a minor component.
         * For example, version 1.0 could be represented as 0x0100. This format
         * implies that versions 0x0100-0x01ff are all API-compatible.
         *
         * In the future, libhardware will expose a hw_get_module_version()
         * (or equivalent) function that will take minimum/maximum supported
         * versions as arguments and would be able to reject modules with
         * versions outside of the supplied range.
         */
        uint16_t module_api_version;
    #define version_major module_api_version
        /**
         * version_major/version_minor defines are supplied here for temporary
         * source code compatibility. They will be removed in the next version.
         * ALL clients must convert to the new version format.
         */
    
        /**
         * The API version of the HAL module interface. This is meant to
         * version the hw_module_t, hw_module_methods_t, and hw_device_t
         * structures and definitions.
         *
         * The HAL interface owns this field. Module users/implementations
         * must NOT rely on this value for version information.
         *
         * Presently, 0 is the only valid value.
         */
        uint16_t hal_api_version;
    #define version_minor hal_api_version
    
        /** Identifier of module */
        const char *id;
    
        /** Name of this module */
        const char *name;
    
        /** Author/owner/implementor of the module */
        const char *author;
    
        /** Modules methods */
        struct hw_module_methods_t* methods;
    
        /** module's dso */
        void* dso;
    
        /** padding to 128 bytes, reserved for future use */
        uint32_t reserved[32-7];
    
    } hw_module_t;
    
    typedef struct hw_module_methods_t {
        /** Open a specific device */
        int (*open)(const struct hw_module_t* module, const char* id,
                struct hw_device_t** device);
    
    } hw_module_methods_t;
    
    /**
     * Every device data structure must begin with hw_device_t
     * followed by module specific public methods and attributes.
     */
    typedef struct hw_device_t {
        /** tag must be initialized to HARDWARE_DEVICE_TAG */
        uint32_t tag;
    
        /**
         * Version of the module-specific device API. This value is used by
         * the derived-module user to manage different device implementations.
         *
         * The module user is responsible for checking the module_api_version
         * and device version fields to ensure that the user is capable of
         * communicating with the specific module implementation.
         *
         * One module can support multiple devices with different versions. This
         * can be useful when a device interface changes in an incompatible way
         * but it is still necessary to support older implementations at the same
         * time. One such example is the Camera 2.0 API.
         *
         * This field is interpreted by the module user and is ignored by the
         * HAL interface itself.
         */
        uint32_t version;
    
        /** reference to the module this device belongs to */
        struct hw_module_t* module;
    
        /** padding reserved for future use */
        uint32_t reserved[12];
    
        /** Close this device */
        int (*close)(struct hw_device_t* device);
    
    } hw_device_t;
    

    4.ハードウェアモジュールライブラリの使用
    ハードウェアモジュールライブラリのマウントと解析はhardware.cのhw_get_module関数は完了し、ハードウェアモジュールライブラリを一定のルールで選択してロードし、HAL_MODULE_INFO_SYMは、ライブラリ内のグローバル変数名を解析し、ハードウェアモジュールライブラリポインタ(hw_module_t構造)を取得し、呼び出し元に返す.
    次に、cameraを例にHALレイヤの使用方法を説明する.
    システムがCameraServiceオブジェクトの作成を開始すると、その関数onFirstRefが呼び出され、その中でhw_get_Module(CAMERA_HARDWARE_MODULE_ID,(const hw_module_t*)&mModule)関数cameraの抽象ハードウェアモジュールcamera_を取得するmoduleは、前述したように、CameraのHALダイナミックライブラリを介してHAL_を解析します.MODULE_INFO_SYMシンボルはグローバル変数を得,取得した抽象ハードウェアモジュール構造によりシステムが持つCamera数などを取得する.具体的なコードはCameraServicesを参照してください.cpp.
    ここでcamera_moduleは、camera HALの抽象ハードウェアモジュールであり、以下のように定義される(camera_common.h).
    typedef struct camera_module {
        hw_module_t common;
    
        /**
         * get_number_of_cameras:
         *
         * Returns the number of camera devices accessible through the camera
         * module.  The camera devices are numbered 0 through N-1, where N is the
         * value returned by this call. The name of the camera device for open() is
         * simply the number converted to a string. That is, "0" for camera ID 0,
         * "1" for camera ID 1.
         *
         * The value here must be static, and cannot change after the first call to
         * this method
         */
        int (*get_number_of_cameras)(void);
    
        /**
         * get_camera_info:
         *
         * Return the static camera information for a given camera device. This
         * information may not change for a camera device.
         *
         */
        int (*get_camera_info)(int camera_id, struct camera_info *info);
    
        /**
         * set_callbacks:
         *
         * Provide callback function pointers to the HAL module to inform framework
         * of asynchronous camera module events. The framework will call this
         * function once after initial camera HAL module load, after the
         * get_number_of_cameras() method is called for the first time, and before
         * any other calls to the module.
         *
         * Version information (based on camera_module_t.common.module_api_version):
         *
         *  CAMERA_MODULE_API_VERSION_1_0, CAMERA_MODULE_API_VERSION_2_0:
         *
         *    Not provided by HAL module. Framework may not call this function.
         *
         *  CAMERA_MODULE_API_VERSION_2_1:
         *
         *    Valid to be called by the framework.
         *
         */
        int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
    
        /**
         * get_vendor_tag_ops:
         *
         * Get methods to query for vendor extension metadata tag information. The
         * HAL should fill in all the vendor tag operation methods, or leave ops
         * unchanged if no vendor tags are defined.
         *
         * Version information (based on camera_module_t.common.module_api_version):
         *
         *  CAMERA_MODULE_API_VERSION_1_x/2_0/2_1:
         *    Not provided by HAL module. Framework may not call this function.
         *
         *  CAMERA_MODULE_API_VERSION_2_2:
         *    Valid to be called by the framework.
         */
        void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
    
        /* reserved for future use */
        void* reserved[8];
    } camera_module_t;
    

    その定義から、最初のメンバーはhw_module_t common、すなわち、上述した自分のハードウェア抽象モジュールにはhw_が含まれる必要があるmodule構造は、「継承」の目的を達成します.また,camera個数の取得やcamera情報の取得など,いくつかの独自のメンバー変数を定義した.hw_の使用get_moduleが取得したcamera_module_t変数はプラットフォームのcamera HAL実装ライブラリにあり、メーカーによってファイル名が異なる場合がありますが、次のような構造(CameraHAL.cpp)が実現されるに違いありません.
    camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
        common : {
            tag                : HARDWARE_MODULE_TAG,
            module_api_version : CAMERA_MODULE_API_VERSION_2_0,
            hal_api_version    : HARDWARE_HAL_API_VERSION,
            id                 : CAMERA_HARDWARE_MODULE_ID,
            name               : "Default Camera HAL",
            author             : "The Android Open Source Project",
            methods            : &gCameraModuleMethods,
            dso                : NULL,
            reserved           : {0},
        },
        get_number_of_cameras : get_number_of_cameras,
        get_camera_info       : get_camera_info,
        set_callbacks         : set_callbacks
    };
    

    カメラのあるHAL層のハードウェア抽象モジュールcamera_module、camera_を通ることができますmoduleハードウェア抽象デバイスcamera_を取得device_tですが、CameraHardwareInterfaceにカプセル化されています.cameraを接続するとき(CameraServiceのconnect関数、最後にCameraClient::initialize)に移動し、CameraHardwareInterfaceオブジェクトを作成し、初期化関数でcamera_を取得します.device_t:int rc = module->methods->open(module, mName.string(), (hw_device_t **)&mDevice);このopen関数は、gCameraModuleMethodsのopen関数であり、以下のように実現されます.
    int Camera::open(const hw_module_t *module, hw_device_t **device)
    {
        ALOGI("%s:%d: Opening camera device", __func__, mId);
        CAMTRACE_CALL();
        pthread_mutex_lock(&mMutex);
        if (mBusy) {
            pthread_mutex_unlock(&mMutex);
            ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
            return -EBUSY;
        }
    
        // TODO: open camera dev nodes, etc
        mBusy = true;
        mDevice.common.module = const_cast(module);
        *device = &mDevice.common;
    
        pthread_mutex_unlock(&mMutex);
        return 0;
    }
    

    ここではcameraに戻りますdevice_t、この構造の初期化は構造関数にあります.
    Camera::Camera(int id)
      : mId(id),
        mStaticInfo(NULL),
        mBusy(false),
        mCallbackOps(NULL),
        mStreams(NULL),
        mNumStreams(0),
        mSettings(NULL)
    {
        pthread_mutex_init(&mMutex, NULL);
        pthread_mutex_init(&mStaticInfoMutex, NULL);
    
        memset(&mDevice, 0, sizeof(mDevice));
        mDevice.common.tag    = HARDWARE_DEVICE_TAG;
        mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0;
        mDevice.common.close  = close_device;
        mDevice.ops           = const_cast(&sOps);
        mDevice.priv          = this;
    }
    

    ,CameraService Camera HAL camera_module_t camera_device_t。 , camera 。 android4.4/hardware/libhardware/modules/camera, c++ , , 。

    5.

    1. HAL hw_get_module hw_module_t 。
    2. HAL hw_module_t->methods->open hw_device_t , open hw_device_t , (close ) 。

    hw_module_t: , hw_get_module 。 hw_module_methods_t , open 。

    hw_device_t: , , 。 hw_module_methods_t open 。

    android hal , android HAL gralloc 。

    : (coder_online), , (java/C/C++/Android/Windows/Linux) , , , 。 , 。