• Android系统HAL基本概念


    1、前言

    Android系统硬件抽象层(Hardware Abstraction Layer),简写为HAL,是连接Android Framework与Linux内核设备驱动的重要桥梁。HAL存在的意义有以下两个方面:

    (1)HAL层屏蔽掉不同硬件设备的差异,为Android提供了统一的设备访问接口。不同的硬件厂商遵循HAL标准来实现自己的硬件控制逻辑,开发者不必关心硬件设备的差异,只需按照HAL提供的标准接口对硬件进行访问即可。

    (2)HAL层帮助硬件厂商隐藏了设备的核心细节,HAL层位于用户空间,遵循Apache协议,允许硬件厂商不公开源码,将设备相关的实现放在HAL层中实现,并以共享库(.so)的形式进行提供。

    下面的图描述了HAL层在Android系统中的位置:

    使用HAL这种设计模式,使得上层服务与底层硬件之间的耦合度降低。

    2、Stub HAL

    Android系统中HAL具有两种实现方式:Legacy以及Stub HAL,初期使用的是Legacy HAL的方式,该方式为标准的Linux共享库,其它应用程序直接调用HAL层共享库导出的函数。Google后来提出了Stub HAL的方式,仍然以共享库(.so)的形式提供,它把所有供外部访问的的方法(函数)的入口指针保存在统一的数据结构,其它程序需要访问HAL中方法时,需要先获得Stub,然后通过具体的函数指针去读写底层设备。

    3、HAL标准接口的定义

    Android已经为常用的硬件设备定义了标准的HAL接口,这些组件有以下:

    当我们需要为这些设备编写HAL层代码时,必须严格按照Google定义的标准接口去实现,否则将导致设备无法在Android Framework下正常工作。

    关于HAL的源码在Android源码树的hardware目录,其中关于Stub方式的HAL实现在libhardware目录下:

    # 常用设备HAL标准接口的头文件
    AOSP/hardware/libhardware/include/hardware
    
    # 常用设备HAL标准接口实现
    AOSP/hardware/libhardware/modules/

    在目录AOSP/hardware/libhardware/include/hardware中包含了一个hardware.h的接口头文件,里面具有比较重要的结构体、变量和函数指针,在开发自己设备的HAL文件时,需要嵌入这些结构体,也就是继承它们的特性,接下来对这些标准接口做介绍。

    首先是struct hw_module_t结构体,定义如下:

    typedef struct hw_module_t {
        uint32_t tag;
        uint16_t module_api_version;
        uint16_t hal_api_version;
        const char *id;
        const char *name;
        const char *author;
        struct hw_module_methods_t* module;
        void* dso;
        uint32_t reserved[32-7];
    } hw_module_t;

    成员简单介绍:

    tag:该值为module的tag,必须定义为HARDWARE_MODULE_TAG;

    module_api_version:模块中API函数接口的版本号;

    hal_api_version:HAL模块接口的API版本号;

    id:硬件的id号,唯一标识模块;

    name:该模块的名称;

    author:模块的作者;

    module:指向封装有open函数指针的结构体,用于模块打开。

    对于struct hw_module_t结构体的理解为,每个硬件通过hw_module_t结构体来描述,我们可以"继承"这个结构体,拓展自己的属性,但是需要注意的是,宿主结构的第一个成员必须是struct hw_module_t类型,硬件对象必须定义一个固定的名字:HMI(Hardware Module Information),每个硬件对象里面都包含了module指针,对应得结构体里面封装了open函数指针,用于打开硬件,并会返回硬件的操作方式。

    接下来是struct hw_module_methods_t结构体的定义,如下所示:

    typedef struct hw_module_methods_t {
        int (*open)(const struct hw_module_t* module, const char* id,
                struct hw_device_t** device);
    
    } hw_module_methods_t;

    该结构体里面封装了一个open函数指针,该函数用于实现打开一个特定的设备,打开的设备通过device二级指针进行返回。

    另外一个重要的结构体为struct hw_device_t,该定义如下:

    typedef struct hw_device_t {
        uint32_t tag;
        uint32_t version;
        struct hw_module_t* module;
        uint32_t reserved[12];
        int (*close)(struct hw_device_t* device);
    } hw_device_t;

    成员简单介绍:

    tag:设备的tag,必须定义为HARDWARE_DEVICE_TAG;

    version:设备操作方式的版本号;

    module:hw_module_t结构体指针,指向设备所属的硬件模块,设备操作接口与硬件模块的联系;

    close:函数指针,关闭该硬件设备的方法。

    对于struct hw_device_t结构体的理解为,硬件设备的操作方法,通过struct module_methods_t结构内的open函数指针将返回hw_device_t结构体指针,从而获得了该硬件设备的操作方法,我们也可以"继承"该结构体,拓展实际硬件设备的操作方式,但是需要注意的是,在宿主结构中,第一个成员必须是struct hw_device_t类型。

    在上面介绍的三个结构之间是紧密联系的,每个硬件模块都由一个struct hw_module_t结构体进行描述,当用户拿到了这个硬件模块,调用其封装的open函数,便返回了硬件设备的操作方法接口,从而便可以调用相关接口对硬件设备进行读写了。

    在HAL标准中还有两个比较重要的宏定义和一个函数,如下:

    /**
     * Name of the hal_module_info
     */
    #define HAL_MODULE_INFO_SYM         HMI
    
    /**
     * Name of the hal_module_info as a string
     */
    #define HAL_MODULE_INFO_SYM_AS_STR  "HMI"
    
    /**
     * Get the module info associated with a module by id.
     *
     * @return: 0 == success, <0 == error and *module == NULL
     */
    int hw_get_module(const char *id, const struct hw_module_t **module);

    在上面的代码中,HAL_MODULE_INFO_SYM为硬件模块固定的变量名,另外一个宏只是字符串的显示,当用户调用hw_get_module()函数时,将硬件的id名进行传入,那么函数将会从当前系统中注册的硬件模块里查找对应的硬件模块,并通过module二级指针进行返回。

    4、小结

    本篇文章对Android系统中HAL的基本概念做简单介绍,另外,对HAL提供的接口进行了简单的描述。

  • 相关阅读:
    view上面 长view时候要设置其frame的,
    controller.allowsEditing = NO;神医,
    怎样计算,遗留,
    编码,一点阅读(转:阮一峰的网络日志),
    原来 ascll是对英文系统的编码,
    CoreGraphics 画图,(转燕羽天空)
    Core Graphics,
    计算数据类型占有 字节的长度,
    浅谈Promise(一)
    原生js实现表格内容增删改
  • 原文地址:https://www.cnblogs.com/Cqlismy/p/11816005.html
Copyright © 2020-2023  润新知