Android HAL简析

前言

Android HAL是Hardware Abstract Layer的缩写,顾名思义,就是硬件抽象层的意思,为什么要搞这么个东西呢,大概是以下原因吧:

  • 软件设计的角度
    抽象层概念是很多软件在设计时都采用的一种设计方法,可以达到抽象和隔离上下层的目的,这样子下层实现变化时,上层逻辑不用改动,这种设计方法在很多开源软件上都可以看到,比如Linux内核的vfs、minigui的gal和ial、ffmpeg、opengl等。
  • 版权方面
    Android基于Linux内核实现,Linux是GPL许可,即对源码的修改都必须开源,而Android是ASL许可,即可以随意使用源码,无需开源,因此将原本应该位于Linux内核的硬件驱动逻辑转移到Android平台来,就可以不必开源,从而保护了厂家的利益。因此Android就提供了一套访问硬件抽象层动态库的接口,各厂商在Android的硬件抽象层实现特定硬件的操作细节,并编译成so库,以库的形式提供给用户使用。

Android HAL支持以下模块:


Android HAL简析_第1张图片

module和device概念

Android HAL定义了两个概念,一个概念是module,即代表上图中的一个模块,表示一个so库,在程序中用hw_module_t表示;一个概念是device,代表module内一个抽象的设备,可以有多个,不一定要对应实际的硬件,在程序中用hw_device_t表示。以上两个结构体只定义通用的接口,每个具体的模块会继承定义本模块自己的接口。以gralloc图像buffer管理模块为例,相关结构体定义如下:

Android HAL简析_第2张图片

可见gralloc定义了一个private_module_t类型的module,定义了一个framebuffer_device_t类型和一个alloc_device_t类型的两个device。

HAL调用流程

上层应用按如下方式调用HAL接口:

  • 调用hw_get_module获取module信息,之后就可以强转成特定模块定义的接口然后调用。hw_get_module先加载id指定模块对应的so库,然后加载符号地址(变量地址),最后将相关信息保存到module中返回,如果是gralloc模块,返回的module就是一个private_module_t类型变量。hw_get_module定义如下:
int hw_get_module(const char *id, const struct hw_module_t **module)

关键代码如下:

#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"

struct hw_module_t *hmi = NULL;
handle = dlopen(path, RTLD_NOW);
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
hmi->dso = handle;

其中path根据平台配置和指定的id拼接出来的,最后的路径类似这样子的:

/system/lib64/hw/gralloc.msm8952.so
  • 调用模块的open方法获取指定的device信息,之后就可以强转成特定设备定义的接口然后调用。open接口是由具体模块实现的,定义如下:
int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

open函数的实现是根据设备id加载指定的device信息,这个加载一般是分配一个对应的device结构体变量,然后填充相关的函数指针等信息,最后将该结构体返回。如果是gralloc模块,返回的device就是一个framebuffer_device_t或者alloc_device_t变量了。

HAL调用示例

以下是GraphicBufferAllocator和GraphicBufferMapper调用gralloc模块的示例代码。

GraphicBufferAllocator::GraphicBufferAllocator()
    : mAllocDev(0)
{
    hw_module_t const* module;
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    gralloc_open(module, &mAllocDev);
}

static inline int gralloc_open(const struct hw_module_t* module, 
        struct alloc_device_t** device) {
    return module->methods->open(module, 
            GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);
}

status_t GraphicBufferAllocator::alloc(uint32_t width, uint32_t height,
        PixelFormat format, uint32_t usage, buffer_handle_t* handle,
        uint32_t* stride)
{
    err = mAllocDev->alloc(mAllocDev, static_cast(width),
            static_cast(height), format, static_cast(usage), handle,
            &outStride);
    return err;
}
GraphicBufferMapper::GraphicBufferMapper()
    : mAllocMod(0)
{
    hw_module_t const* module;
    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    mAllocMod = reinterpret_cast(module);
}

status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
{
    err = mAllocMod->registerBuffer(mAllocMod, handle);
    return err;
}

你可能感兴趣的:(Android HAL简析)