美文网首页
Android HAL简析

Android HAL简析

作者: Jimmy2012 | 来源:发表于2017-10-15 20:57 被阅读70次

    前言

    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支持以下模块:


    module和device概念

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

    可见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<int>(width),
                static_cast<int>(height), format, static_cast<int>(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<gralloc_module_t const *>(module);
    }
    
    status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
    {
        err = mAllocMod->registerBuffer(mAllocMod, handle);
        return err;
    }
    

    相关文章

      网友评论

          本文标题:Android HAL简析

          本文链接:https://www.haomeiwen.com/subject/yedcuxtx.html