HAL 架构

 

hardware/libhardware/include/hardware/hardware.h

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;

typedef struct hw_module_t {
    uint32_t tag;
    uint16_t module_api_version;
    uint16_t 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;

/**
 * Every device data structure must begin with hw_device_t
 * followed by module specific public methods and attributes.
 */
typedef struct hw_device_t {
    uint32_t tag;
    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);   // 该设备的关闭函数指针,可以看做硬件的close方法
} hw_device_t;

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    return hw_get_module_by_class(id, NULL, module);
}

    每一个硬件都通过hw_module_t来描述,我们称之为一个硬件对象。你可以去“继承”这个hw_module_t,然后扩展自己的属性,硬件对象必须定义为一个固定的名字:HMI,即:Hardware Module Information的简写,每一个硬件对象里都封装了一个函数指针open用于打开该硬件,我们理解为硬件对象的open方法,open调用后返回这个硬件对应的Operation interface。

   硬件对象hw_module_t的open方法返回该硬件的Operation interface,它由hw_device_t结构体来描述,我们称之为:该硬件的操作接口

-------------------------------------------------------------------------

下面以audio模块为例子来说明如何实现。

hardware/libhardware/include/hardware/audio.h

struct audio_module {
    struct hw_module_t common;   //看来audio_module没啥特殊的,沿用hw_module_t  而且audio_hw_device->common中就保存了这个字段。直接强转就行了
};


struct audio_hw_device {
    /**
     * Common methods of the audio device.  This *must* be the first member of audio_hw_device
     * as users of this structure will cast a hw_device_t to audio_hw_device pointer in contexts
     * where it's known the hw_device_t references an audio_hw_device.
     */
    struct hw_device_t common; //保存的一些基本信息,任何一个硬件模块都会有这个

    uint32_t (*get_supported_devices)(const struct audio_hw_device *dev);
    int (*init_check)(const struct audio_hw_device *dev);
    int (*set_voice_volume)(struct audio_hw_device *dev, float volume);
    int (*set_master_volume)(struct audio_hw_device *dev, float volume);
    int (*get_master_volume)(struct audio_hw_device *dev, float *volume);
    int (*set_mode)(struct audio_hw_device *dev, audio_mode_t mode);
    int (*set_mic_mute)(struct audio_hw_device *dev, bool state);
    int (*get_mic_mute)(const struct audio_hw_device *dev, bool *state);
    int (*set_parameters)(struct audio_hw_device *dev, const char *kv_pairs);
    char * (*get_parameters)(const struct audio_hw_device *dev, const char *keys);
    size_t (*get_input_buffer_size)(const struct audio_hw_device *dev, const struct audio_config *config);
    int (*open_output_stream)(struct audio_hw_device *dev,
                              audio_io_handle_t handle,
                              audio_devices_t devices,
                              audio_output_flags_t flags,
                              struct audio_config *config,
                              struct audio_stream_out **stream_out,
                              const char *address);

    void (*close_output_stream)(struct audio_hw_device *dev, struct audio_stream_out* stream_out);

    int (*open_input_stream)(struct audio_hw_device *dev,
                             audio_io_handle_t handle,
                             audio_devices_t devices,
                             struct audio_config *config,
                             struct audio_stream_in **stream_in,
                             audio_input_flags_t flags,
                             const char *address,
                             audio_source_t source);

    void (*close_input_stream)(struct audio_hw_device *dev, struct audio_stream_in *stream_in);
    int (*dump)(const struct audio_hw_device *dev, int fd);
    int (*set_master_mute)(struct audio_hw_device *dev, bool mute);
    int (*get_master_mute)(struct audio_hw_device *dev, bool *mute);

    int (*create_audio_patch)(struct audio_hw_device *dev,
                               unsigned int num_sources,
                               const struct audio_port_config *sources,
                               unsigned int num_sinks,
                               const struct audio_port_config *sinks,
                               audio_patch_handle_t *handle);

    int (*release_audio_patch)(struct audio_hw_device *dev,
                               audio_patch_handle_t handle);

    int (*get_audio_port)(struct audio_hw_device *dev,
                          struct audio_port *port);

    int (*set_audio_port_config)(struct audio_hw_device *dev,
                         const struct audio_port_config *config);

};

typedef struct audio_hw_device audio_hw_device_t;


// common audio stream parameters and operations 
// audio_stream_out和audio_stream_in的公共模块
//大概C语言没有继承的说法,也就只有这种方式来达到代码复用
struct audio_stream {
    uint32_t (*get_sample_rate)(const struct audio_stream *stream);
    int (*set_sample_rate)(struct audio_stream *stream, uint32_t rate);
    size_t (*get_buffer_size)(const struct audio_stream *stream);
    audio_channel_mask_t (*get_channels)(const struct audio_stream *stream);
    audio_format_t (*get_format)(const struct audio_stream *stream);
    int (*set_format)(struct audio_stream *stream, audio_format_t format);
    int (*standby)(struct audio_stream *stream);
    int (*dump)(const struct audio_stream *stream, int fd);
    audio_devices_t (*get_device)(const struct audio_stream *stream);
    int (*set_device)(struct audio_stream *stream, audio_devices_t device);
    int (*set_parameters)(struct audio_stream *stream, const char *kv_pairs);
    char * (*get_parameters)(const struct audio_stream *stream, const char *keys);
    int (*add_audio_effect)(const struct audio_stream *stream, effect_handle_t effect);
    int (*remove_audio_effect)(const struct audio_stream *stream, effect_handle_t effect);
};


struct audio_stream_out {
    /**
     * Common methods of the audio stream out.  This *must* be the first member of audio_stream_out
     * as users of this structure will cast a audio_stream to audio_stream_out pointer in contexts
     * where it's known the audio_stream references an audio_stream_out.
     */
    struct audio_stream common;

    // Return the audio hardware driver estimated latency in milliseconds.
    uint32_t (*get_latency)(const struct audio_stream_out *stream);
    int (*set_volume)(struct audio_stream_out *stream, float left, float right);
    ssize_t (*write)(struct audio_stream_out *stream, const void* buffer, size_t bytes);

    /* return the number of audio frames written by the audio dsp to DAC since
     * the output has exited standby
     */
    int (*get_render_position)(const struct audio_stream_out *stream, uint32_t *dsp_frames);

    int (*get_next_write_timestamp)(const struct audio_stream_out *stream, int64_t *timestamp);

    /**
     * set the callback function for notifying completion of non-blocking
     * write and drain.
     * Calling this function implies that all future write() and drain()
     * must be non-blocking and use the callback to signal completion.
     */
    int (*set_callback)(struct audio_stream_out *stream, stream_callback_t callback, void *cookie);
    int (*pause)(struct audio_stream_out* stream);
    int (*resume)(struct audio_stream_out* stream);
    int (*drain)(struct audio_stream_out* stream, audio_drain_type_t type );
    int (*flush)(struct audio_stream_out* stream);
};

typedef struct audio_stream_out audio_stream_out_t;

struct audio_stream_in {
    /**
     * Common methods of the audio stream in.  This *must* be the first member of audio_stream_in
     * as users of this structure will cast a audio_stream to audio_stream_in pointer in contexts
     * where it's known the audio_stream references an audio_stream_in.
     */
    struct audio_stream common;

    // set the input gain for the audio driver. This method is for future use
    int (*set_gain)(struct audio_stream_in *stream, float gain);
    ssize_t (*read)(struct audio_stream_in *stream, void* buffer, size_t bytes);
    uint32_t (*get_input_frames_lost)(struct audio_stream_in *stream);
};

再看audio_hw.c,这文件命名,没看出规律来。

hardware/qcom/audio/hal/audio_hw.c
static int adev_open(const hw_module_t *module, const char *name,
                     hw_device_t **device)
{
    int i, ret;

    ALOGD("%s: enter", __func__);
    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;

    pthread_mutex_lock(&adev_init_lock);
    if (audio_device_ref_count != 0){
            *device = &adev->device.common;
            audio_device_ref_count++;
            ALOGD("%s: returning existing instance of adev", __func__);
            ALOGD("%s: exit", __func__);
            pthread_mutex_unlock(&adev_init_lock);
            return 0;
    }

    adev = calloc(1, sizeof(struct audio_device));

    pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);

    adev->device.common.tag = HARDWARE_DEVICE_TAG;
    adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
    adev->device.common.module = (struct hw_module_t *)module;
    adev->device.common.close = adev_close;

    adev->device.init_check = adev_init_check;
    adev->device.set_voice_volume = adev_set_voice_volume;
    adev->device.set_master_volume = adev_set_master_volume;
    adev->device.get_master_volume = adev_get_master_volume;
    adev->device.set_master_mute = adev_set_master_mute;
    adev->device.get_master_mute = adev_get_master_mute;
    adev->device.set_mode = adev_set_mode;
    adev->device.set_mic_mute = adev_set_mic_mute;
    adev->device.get_mic_mute = adev_get_mic_mute;
    adev->device.set_parameters = adev_set_parameters;
    adev->device.get_parameters = adev_get_parameters;
    adev->device.get_input_buffer_size = adev_get_input_buffer_size;
    adev->device.open_output_stream = adev_open_output_stream;
    adev->device.close_output_stream = adev_close_output_stream;
    adev->device.open_input_stream = adev_open_input_stream;
    adev->device.close_input_stream = adev_close_input_stream;
    adev->device.dump = adev_dump;

    /* Set the default route before the PCM stream is opened */
    adev->mode = AUDIO_MODE_NORMAL;
    adev->active_input = NULL;
    adev->primary_output = NULL;
    adev->out_device = AUDIO_DEVICE_NONE;
    adev->bluetooth_nrec = true;
    adev->acdb_settings = TTY_MODE_OFF;
    /* adev->cur_hdmi_channels = 0;  by calloc() */
    adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
    voice_init(adev);
    list_init(&adev->usecase_list);
    adev->cur_wfd_channels = 2;

    pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
    adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;

    /* Loads platform specific libraries dynamically */
    adev->platform = platform_init(adev);
    if (!adev->platform) {
        free(adev->snd_dev_ref_cnt);
        free(adev);
        ALOGE("%s: Failed to init platform data, aborting.", __func__);
        *device = NULL;
        pthread_mutex_unlock(&adev_init_lock);
        return -EINVAL;
    }

    adev->snd_card_status.state = SND_CARD_STATE_ONLINE;

    //.................

    *device = &adev->device.common;

    audio_device_ref_count++;
    pthread_mutex_unlock(&adev_init_lock);

    ALOGV("%s: exit", __func__);
    return 0;
}


static struct hw_module_methods_t hal_module_methods = {
    .open = adev_open,  //用这个方法初始化
};

//HAL_MODULE_INFO_SYM存储了audio模块所有相关信息
//可能有个audio_hw_device记录了这个信息
struct audio_module HAL_MODULE_INFO_SYM = {      //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 = "QCOM Audio HAL", .author = "The Linux Foundation", .methods = &hal_module_methods, }, };

 ----------------------------------------------------------

上层如何实现 可以参考http://www.cnblogs.com/muhe221/articles/4462320.html 这里只做简要说明

AudioPolicyInterface  AudioPolicyClientInterface //这两个一个是服务端,一个是客户端。他们没有共同的接口
audio_policy           audio_policy_service_ops
两组互相对应

//frameworks/av/services/audiopolicy/AudioPolicyManager.h
class AudioPolicyManager: public AudioPolicyInterface {
AudioPolicyManager(AudioPolicyClientInterface *clientInterface); //构造函数
//................
    AudioPolicyClientInterface *mpClientInterface;
}

//hardware/libhardware_legacy/audio/AudioPolicyCompatClient.h
class AudioPolicyCompatClient : public AudioPolicyClientInterface {
      AudioPolicyCompatClient(struct audio_policy_service_ops *serviceOps, void *service) : mServiceOps(serviceOps) , mService(service) {}

private:
    struct audio_policy_service_ops* mServiceOps;
    void* mService;
  //......
}

hardware/libhardware/include/hardware/audio_policy.h
typedef struct audio_policy_module {
    struct hw_module_t common;             //hw_module_t => audio_module => audio_policy_module(audio_policy_module_t)都是同一类型。
} audio_policy_module_t;

struct audio_policy_device {   //又封装了一层
    /**
     * Common methods of the audio policy device.  This *must* be the first member of
     * audio_policy_device as users of this structure will cast a hw_device_t to
     * audio_policy_device pointer in contexts where it's known the hw_device_t references an
     * audio_policy_device.
     */
    struct hw_device_t common;

    int (*create_audio_policy)(const struct audio_policy_device *device,
                               struct audio_policy_service_ops *aps_ops,
                               void *service,
                               struct audio_policy **ap);

    int (*destroy_audio_policy)(const struct audio_policy_device *device,
                                struct audio_policy *ap);
};

 

 
posted @ 2015-04-28 12:11  牧 天  阅读(809)  评论(0)    收藏  举报