Android为了屏蔽硬件的复杂性,设计了一个HAL层,HardwareAbstarct Layer,即硬件抽象层。HAL层位于驱动和framework之间,为各个硬件厂家提供的形形色色的驱动模块规定了统一的接口。在Android里面,这些接口是用c语言描述的,而在c语言中,接口都是用函数指针来描述的。所以我们在这些接口模块中看到大量函数指针,下面的驱动去实现这些接口,并挂载到这些接口模块上。

这些接口模块本质上就是一些so库,采用动态加载的形式被framework层调用。Framwork层会在使用到某个功能时去尝试dlopen对应的so库,若这个库存在,调用它,若不存在,就认为系统不支持这个功能。完成查找这个硬件模块是否存在,以及去dlopen,dlsym该模块的初始化函数的那些逻辑放在libhardware.so中。那么,framework和hal的关系可以形象的表示为这样的模型:

android 多个audio record 冲突 android hardware audio_android

Audio_interfaces中定义了HAL层的Audio模块(一些so库),比如

static const char * constaudio_interfaces[] = {
   AUDIO_HARDWARE_MODULE_ID_PRIMARY,
    AUDIO_HARDWARE_MODULE_ID_A2DP,
AUDIO_HARDWARE_MODULE_ID_USB,
}

AudioFlinger使用loadHwModule_l来加载audioInterfaces。实际是去加载HAL层得一些so库。用函数hw_get_module_by_class拿到module,然后用audio_hw_device_open拿到device。所有的HAL层的硬件module都是这么干的。这俩函数定义在libhardware.so中,在编译audioflinger.so时, 这个库是作为动态共享库参加链接的。

我们来看看具体过程:

static intload_audio_interface(const char *if_name, audio_hw_device_t **dev)
{
    const hw_module_t *mod;
    int rc;
 
    rc =hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
    ALOGE_IF(rc, "%s couldn't load audiohw module %s.%s (%s)", __func__,
                 AUDIO_HARDWARE_MODULE_ID,if_name, strerror(-rc));
    if (rc) {
        goto out;
    }
    rc = audio_hw_device_open(mod, dev);
    ALOGE_IF(rc, "%s couldn't open audiohw device in %s.%s (%s)", __func__,
                 AUDIO_HARDWARE_MODULE_ID,if_name, strerror(-rc));
    if (rc) {
        goto out;
    }
    if ((*dev)->common.version <AUDIO_DEVICE_API_VERSION_MIN) {
        ALOGE("%s wrong audio hw deviceversion %04x", __func__, (*dev)->common.version);
        rc = BAD_VALUE;
        goto out;
    }
    return 0;
 
out:
    *dev = NULL;
    return rc;
}

hw_get_module_by_class是在/hardware/libhardware/hardware.c中定义的,这个文件和libhardware/include/hardware/hardware.h一起定义了hal的接口。

有两个基本的结构体:

一个是hw_module_t,定义了模块的一些id,名称,作者等描述信息,

另一个是hw_device_t,没定义太多东西,但是它的继承结构体定义了一个模块对外需要暴露的接口

再看看继承这两个结构体的audio机子的结构体,定义在audio.h (hardware\libhardware\include\hardware),这里定义了:

struct audio_module {
    struct hw_module_t common;
};
 
struct audio_hw_device {
struct hw_device_t common;
。。。
}
struct audio_stream_out {
 
};
struct audio_stream {

};
 
struct audio_stream_in {
};




具体的HAL层模块通过继承这两个结构体来实现具体的业务功能。


然后调用dlopen打开so库,然后const char *sym =HAL_MODULE_INFO_SYM_AS_STR;

hmi = (struct hw_module_t *)dlsym(handle, sym);
而在hardware.h中
#defineHAL_MODULE_INFO_SYM_AS_STR "HMI"

所以是拿到名为HMI的符号

而在audio_hw.c的最后,定义了

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 = "Default audio HWHAL",
        .author = "The Android Open SourceProject",
        .methods = &hal_module_methods,
    },
};



注意libhardware/include/hardware/audio.h中,定义了

struct audio_module {
    struct hw_module_t common;
};

可以认为audio_module是hw_module_t的子类。

回到load_audio_interface,这是通过hw_get_module_by_class拿到了hw_module_t

然后在调用audio_hw_device_open(mod,dev),本质上是调用module->methods->open拿到了hw_device_t的子类audio_hw_device_t。

typedef struct hw_device_t {
    uint32_t tag;
    uint32_t version;
    struct hw_module_t* module;
#ifdef __LP64__
    uint64_t reserved[12];
#else
    uint32_t reserved[12];
#endif
    int (*close)(struct hw_device_t* device);
} hw_device_t;
typedef struct audio_hw_deviceaudio_hw_device_t


structaudio_hw_device {
    struct hw_device_t common;
uint32_t (*get_supported_devices)(const structaudio_hw_device *dev);
。。。。
}

这时就拿到了audio_hw_device_t,这个结构体全是各种函数指针,这些指针都已经在调用module->methods->open时已经赋值过了。

所以此时进程拿到了so的接口。而且具有很好的灵活性

而在Load module之后,会调用module的open函数,我们看看这个module是怎么定义的

static_t struct hw_module_methods_t hal_module_methods ={
    .open =adev_open,
};
 
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 ="Manta audio HW HAL",
        .author ="The Android Open Source Project",
        .methods =&hal_module_methods,
    },
};



而open就是为audio_hw_device 赋值,而且还会赋值一些环境相关的结构体和变量,他们一起组成了audio_device.我们可以认为,audio_hw_device里的接口都是暴露给外面的接口。

struct audio_device {
    structaudio_hw_device hw_device;
。。。
}

就是一个继承了hw_device_t的audio_hw_device。