Android的硬件抽象层模块编写规范

简介: 版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/47950221 硬件抽象层...
版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/47950221

硬件抽象层模块编写规范

Android系统的硬件抽象层以模块的形式来管理各个硬件访问接口.每一个硬件模块都对应有一个动态链接库文件.这些动态链接库文件的命令需要符合一定的规范.同时,在系统内部,每一个硬件抽象层模块都使用结构体hw_module_t来描述,而硬件设备则使用结构体hw_device_t来描述.下面我们跟着老罗来学习描述硬件抽象层模块文件的命名规范以及结构体hw_module_t和hw_device_t的定义.

1:硬件抽象层模块文件命名规范
硬件抽象层模块文件的命名规范定义在hardware/libhardware/hardware.c文件中.

/**
 * There are a set of variant filename for modules. The form of the filename
 * is "<MODULE_ID>.variant.so" so for the led module the Dream variants 
 * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
 *
 * led.trout.so
 * led.msm7k.so
 * led.ARMV6.so
 * led.default.so
 */
static const char *variant_keys[] = {
    "ro.hardware",  /* This goes first so that it can pick up a different
                       file on the emulator. */
    "ro.product.board",
    "ro.board.platform",
    "ro.arch"
};

这段代码和注释的意思是,硬件抽象层模块文件的命名规范为".variant.so",其中,MODULE_ID表示模块的ID,variant表示四个系统属性ro.hardware,ro.product.board,ro.board.platform,ro.arch 之一.系统在加载硬件抽象层模块的时候,以此按照ro.hardware,ro.product.board,ro.board.platform,ro.arch的顺序来取他们的属性值.如果其中的一个属性存在,那么就把他的值作为variant的值,然后在检查对应的文件是否存在,如果存在,那么就找到要加载的硬件抽象层模块文件了.否则,就继续找下一个系统属性.如果这四个系统属性都不存在,或者对应这四个系统属性的硬件抽象层模块文件不存在,那么就使用”MODULE_ID.default.so”来作为要加载的硬件抽象层模块文件的名称.

系统属性ro.hardware是在系统启动时,由init进程负责设置.它首先会读取/proc/cmdline文件,检查里面有没有一个名称为androidboot.hardware的属性,如果有,就把他的值作为属性ro.hardware的值,否则,就将/proc/cpuinfo文件的内容读取出来,并且将里面的硬件信息解析出来,即将Hardware字段的内容作为属性ro.hardware的值.例如,在Android模拟器中,从/proc/cpuinfo文件读取出来的Hardware字段内容为goldfish,于是,init进程会将属性ro.hardware的值设置为”goldfish”.系统属性ro.product.board,ro.board.platform,ro.arch是从/system/build.prop文件读取出来的.文件/system/build.prop是由编译系统中的编译脚本build/core/Makefile和Shell脚本build/tools/buildinfo.sh生成的.

2:硬件抽象层模块结构体定义规范

结构体hw_module_t和hw_device_t以及其相关的其他结构体定义在文件hardware/libhardware/include/hardware/hardware.h中.

/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 *
 * 每一个硬件模块肯定会有一个名为HAL_MODULE_INFO_SYM的数据结构,并且
 * 这个数据结构的域一定是以hw_module_t开始,后面跟着模块特殊的信息.
 *
 */
typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    /** tag一定要被初始化为HARDWARE_MODULE_TAG  */
    uint32_t tag;
    /** major version number for the module */
    /** 这个模块的主版本号码  */  
    uint16_t version_major;
    /** minor version number of the module */
    /** 这个模块的小版本号 */
    uint16_t version_minor;
    /** 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 */
    /** 模块的dso */
    void* dso;
    /** padding to 128 bytes, reserved for future use */
    /** 填充到128字节,为以后的使用所保留 */
    uint32_t reserved[32-7];
} hw_module_t;

结构体hw_module_t中的每一个成员的注释都已经在上面翻译了,不过,有几个点需要注意:

1):在结构体hw_module_t的定义前面有一段注释,意思是硬件抽象层中的每一个模块都必须自定义一个硬件抽象层模块结构体,而且他的第一个成员变量的类型必须为hw_module_t.

2):硬件抽象层每一个模块都必须存在一个导出符号HAL_MODULE_INFO_SYM,即HMI,他指向一个自定义的硬件抽象层模块结构体.

3):结构体hw_module_t的成员变量tag的值必须设置为HARDWARE_MODULE_TAG,即设置为一个常量值(‘H’ << 24 | ‘W’ << 16 | ‘M’ << 18 | ‘T’),用来标志这是一个硬件抽象层结构体.

4):结构体hw_module_t的成员变量dso用来保存加载硬件抽象层模块后得到的句柄值.前面提到,每一个硬件抽象层都对应一个动态链接库文件.加载硬件抽象层模块的过程实际上就是调用dlopen函数来加载与其对应的动态链接库文件的过程.在调用dlclose函数来卸载这个硬件抽象层模块的时候,要用到这个句柄值,因此,我们在加载时需要将他保存起来.

5):结构体hw_module_t的成员变量定义了一个硬件抽象层模块的操作方法列表,他的类悉为hw_module_methods_t.

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;

结构体hw_module_methods_t只有一个成员变量,他是一个函数指针,用来打开硬件抽象层模块中的硬件设备.其中,参数module表示要打开的硬件设备所在的模块,参数id表示要打开的设备的ID,参数device是一个输出参数,用来描述一个已经打开的硬件设备.由于一个硬件抽象层模块可能包含多个设备硬件,因此,在调用结构体hw_moduel_methods_t的成员变量open来打开一个硬件设备的时候,我们需要指定他的ID.硬件抽象层中的硬件设备使用结构体hw_device_t来描述.


/**
 * Every device data structure must begin with hw_device_t
 * followed by module specific public methods and attributes.
 *
 * 每一个设备数据结构都是以hw_device_t开始的,后面跟着模块特定的
 * 公共方法和属性.
 */
typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    /** tag一定要被初始化为HARDWARE_DEVICE_TAG */
    uint32_t tag;
    /** version number for hw_device_t */
    /** hw_device_t的版本号 */
    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);
} hw_device_t;

1):硬件抽象层模块中的每一个硬件设备都必须自定义一个硬件设备结构体,而且他的第一个成员变量参数为hw_device_t

2):构体hw_device_t的成员变量tag的值必须设置为HARDWARE_DEVICE_TAG,即设置为一个常量值(‘H’ << 24 | ‘W’ << 16 | ‘M’ << 18 | ‘T’),用来标志这是一个硬件抽象层中的硬件设备结构体.

3):结构体hw_device_t中的成员变量close是一个函数指针,他用来关闭一个硬件设备.

注意:硬件抽象层中的硬件设备是由其所在的模块提供接口来打开的,而关闭则是由硬件设备自身提供的接口来完成的.

目录
相关文章
|
1月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
142 4
|
7月前
|
Android开发
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
Android MediaTek 平台增加UART接口的红外模块支持,支持NEC红外遥控
150 0
|
4月前
|
存储 编解码 网络协议
Android平台GB28181执法记录仪硬件选型和国标技术实现探讨
前几年,我们在做Android平台GB28181设备接入模块的时候,第一个使用场景想到的就是用在公检法应急指挥等场景下的执法记录仪,本篇blog,我们主要围绕Android平台GB28181执法记录仪的硬件选型、设备接入、音视频流配置、流媒体传输、存储和管理、控制与控制中心等方面进行设计,探讨下Android平台GB28181设备接入模块在执法记录仪行业的应用。
Android平台GB28181执法记录仪硬件选型和国标技术实现探讨
|
4月前
|
编解码 网络协议 前端开发
如何实现Android平台GB28181设备接入模块按需打开摄像头并回传数据
后台采集摄像头,如果想再进一步扩展,可以把android平台gb28181的camera2 demo,都移植过来,实现功能更强大的国标设备侧,这里主要是展示,收到国标平台侧的回传请求后,才打开摄像头,才开始编码打包,最大限度的减少资源的占用
|
4月前
|
编解码 网络协议 Android开发
Android平台GB28181设备接入模块实现后台service按需回传摄像头数据到国标平台侧
我们在做Android平台GB28181设备对接模块的时候,遇到这样的技术需求,开发者希望能以后台服务的形式运行程序,国标平台侧没有视频回传请求的时候,仅保持信令链接,有发起视频回传请求或语音广播时,打开摄像头,并实时回传音视频数据或接收处理国标平台侧发过来的语音广播数据。
|
4月前
|
Java Android开发
添加Flutter模块到已有项目(Android)
添加Flutter模块到已有项目(Android)
52 3
|
4月前
|
监控 Java 开发工具
如何快速对接Android平台GB28181接入模块(SmartGBD)
大牛直播SDK推出的Android平台GB28181接入SDK(SmartGBD),可实现不具备国标音视频能力的 Android终端,通过平台注册接入到现有的GB/T28181—2016服务,可用于如执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终端等场景,可能是业内为数不多功能齐全性能优异的商业级水准GB28181接入SDK。
|
4月前
|
编解码 开发工具 Android开发
Android平台RTMP直播推送模块技术接入说明
大牛直播SDK跨平台RTMP直播推送模块,始于2015年,支持Windows、Linux(x64_64架构|aarch64)、Android、iOS平台,支持采集推送摄像头、屏幕、麦克风、扬声器、编码前、编码后数据对接,功能强大,性能优异,配合大牛直播SDK的SmartPlayer播放器,轻松实现毫秒级的延迟体验,满足大多数行业的使用场景。RTMP直播推送模块数据源,支持编码前、编码后数据对接
|
4月前
|
监控 开发工具 Android开发
结合GB/T28181规范探讨Android平台设备接入模块心跳实现
本文介绍了GB28181标准中的状态信息报送机制,即心跳机制,用于监控设备与服务器间的连接状态。根据国标GB/T28181-2016,设备在异常时需立即发送状态信息,在正常状态下则按固定间隔(默认60秒)定期发送。若连续三次(默认值)未收到心跳,则视为离线。文章展示了在Android平台的GB28181设备接入模块(SmartGBD)中,如何调整心跳间隔为20秒及超时次数为3次,并给出了心跳消息的示例和异常处理代码片段。对于希望深入了解或遇到问题的开发者,作者提供了进一步交流的机会。
|
4月前
|
编解码 API 开发工具
Android平台轻量级RTSP服务模块二次封装版调用说明
本文介绍了Android平台上轻量级RTSP服务模块的二次封装实践,旨在简化开发流程,让开发者能更专注于业务逻辑。通过`LibPublisherWrapper`类提供的API,可在应用中轻松初始化RTSP服务、配置视频参数(如分辨率、编码类型)、启动与停止RTSP服务及流发布,并获取RTSP会话数量。此外,还展示了如何处理音频和视频数据的采集与推送。最后,文章提供了从启动服务到销毁资源的完整示例,帮助开发者快速集成实时流媒体功能。