【手写实例】HAL层实例写完后知识点总结。

HAL层实例完成后知识点总结。

手动写完hal实例这里总结几个知识点。
源码:(开始同步github啦,希望有人支持)
https://github.com/cshang983255766/MyAndroidOpenTest/tree/master/myfake

1.驱动属于内核空间,调用驱动的client属于用户空间。hal就是这两个空间的链接。了解过binder之后,觉得binder和hal的关系很密切。后面写向上层调用服务接口时会涉及到。

这里总结一下个人理解:1、硬件抽象层的动态库会在系统启动时自动加载,加载时会自动调用hw_module_methods_t 结构体中的open方法,
与驱动绑定。
2、硬件抽象层是通过jni供给服务层用的,client进程是通过binder和servicemanager来找到服务的。系统启动时会在systemserver中
把服务add到servicemanager中。加载的时候会加一个服务独有的句柄。client进程想调服务时,
在进程中通过xxx = xxx.Stub.asInterface(ServiceManager.getService(句柄))来获取到服务,此时xxx就拥有了在
服务接口(xxx.aidl)中定义的方法。这些方法通过服务-->jni-->hal-->driver(kernel space)索引到驱动层的函数。

2、知道hal是链接内核空间和用户空间之后,那具体是怎么链接的呢?接口通过什么规则定义呢?
硬件抽象层有两个重要的数据结构:硬件模块结构体 hw_module_t 和 硬件接口结构体 hw_device_t。
Android HAL 将各类硬件设备抽象为硬件模块,使用 hw_module_t 来描述这一模块,每个硬件抽象模块都对应一个动态链接库,这一般是由厂商提供的。
而每一类硬件抽象模块又包含多个独立的硬件设备,使用 hw_device_t 结构体描述硬件模块中的独立硬件设备。
HAL 规定每个硬件模块必须包含一个 HAL_MODULE_INFO_SYM 的结构体,这个结构体的第一个元素必须为 hw_module_t,然后后面可以增加模块相关的其他信息。其中,tag属性也必须为 HARDWARE_MODULE_TAG 常量。
以上几行是网上看得到别人总结的。可供参考。
自己总结如下:
1>文件树:

android4.2.2\hardware\libhardware
    ----include
        ----hardware
            ----myfake.h
    ----modules
        ----myfake
            ----myfake.cpp
            ----Android.mk

2>两个重要的结构体

hw_module_t和hw_device_t 。
hw_module_t用来描述某个模块,hw_device_t用于描述模块下的设备,

//硬件模块结构体
struct myfake_module_t
{
    struct hw_module_t common;
};

//硬件接口结构体
struct myfake_device_t
{
    struct hw_device_t common;
    int fd;
    int (*set_val)(struct myfake_device_t* dev, int val);
    int (*get_val)(struct myfake_device_t* dev, int* val);
};

hal注册的时候会首先注册module:

//定义模块结构体变量
struct myfake_module_t HAL_MODULE_INFO_SYM = {  //此处必须是HAL_MODULE_INFO_SYM。否则系统索引不到。
    common :  
    {
        tag : HARDWARE_MODULE_TAG,
        version_major : 1,
        version_minor : 0,
        id : MYFAKE_HARDWARE_MODULE_ID,
        name : MODULE_NAME,
        author : MODULE_AUTHOR,
        methods : &myfake_module_methods,   //模块中的方法一般是open方法,用途打开module中的device。
    },
};

通过结构体中的id来索引hal中的设备和方法。其中dev->common.tag必须为HARDWARE_DEVICE_TAG。

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (hw_module_t*)module;
    dev->common.close = myfake_device_close;
    dev->set_val = myfake_set_val;
    dev->get_val = myfake_get_val;

至此就打通了经脉。其他写法规则可以查hardware/libhardware/include/hardware/hardware.h

3、hal是以动态库的形式加载到系统中,放在/system/lib/hw 目录下。当client调用module->methods->open(module, MYFAKE_HARDWARE_MODULE_ID, (struct hw_device_t **)device);方法时,系统会通过MYFAKE_HARDWARE_MODULE_ID找到对应的.so文件。
并且对编译生成的文件名也有要求必须为<MYFAKE_HARDWARE_MODULE_ID>.default.so。其中default也可以为其他ro.hardware、ro.product.board、ro.board.platform和ro.arch其中之一。

另外:(其中myfake是我的驱动名称)
我们将硬件抽象层模块myfake对应的文件名称定义为myfake.default,编译成功后,系统就会自动在后面加后缀.so,于是就得到了一个myfake.default.so文件。根据硬件抽象层模块文件的命名规范,当我们要加载硬件抽象层模块myfake时,只需要指定它的名字,即“myfake‖,系统就会根据一定的规则成功地找到要加载的myfake.default.so文件。
这里顺便说一下硬件抽象层模块的命名规范以及加载顺序。硬件抽象层模块文件的命名规范为“<MODULE_ID>.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‖来作为要加载的硬件抽象层模块文件的名称。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值