HAL接口层 --- hardware模块接口

下面分析一个文件hardware/libhardware/hardware.c,这个文件提供了一些函数,上层通过这些函数可以用来查找加载HAL库,

以及获取指定HAL库的模块变量;

load方法如下,

static int load(const char *id, const char *path,const struct hw_module_t **pHmi)
{
int status;
void *handle;
struct hw_module_t *hmi;
handle = dlopen(path, RTLD_NOW);
•••

这个接口是一个内部函数,逻辑如下:

1,首先先加载path指定的HAL动态库

2,然后通过下面的代码

const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);

从动态库中获取模块名为HMI的模块,  在hardware/libhardware/include/hardware.h中有如下宏定义:

#define HAL_MODULE_INFO_SYM HMI
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"

因此HAL模块变量必须定义成HAL_MODULE_INFO_SYM才能被正确获取;

3, 检测模块id是否匹配,匹配才能成功获取到模块变量

hw_module_exists方法如下,

static int hw_module_exists(char *path, size_t path_len,const char *name, const char *subname)
{
snprintf(path, path_len, "%s/%s.%s.so",HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;
return -ENOENT;
}

该函数会填充path字符串,填充后path描述的路径为HAL_LIBRARY_PATHX/name.subname.so,先后判断HAL_LIBRARY_PATH2和HAL_LIBRARY_PATH1中的模块是否存在,只要有一个存在就返回0.

其中的HAL_LIBRARY_PATHX定义如下

#if defined(__LP64__)
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#else
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#endif

hw_get_module_by_class方法如下,

int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i;
char prop[PATH_MAX];
char path[PATH_MAX];
char name[PATH_MAX];
char prop_name[PATH_MAX];
•••

这个函数通过模块ID class_id获取到对应的模块变量,以上面的sensor模块为例,逻辑如下:

1, 这里的inst 为NULL,因此name 就是class_id ,sensor 模块就是SENSORS_HARDWARE_MODULE_ID(sensors)

2, 设置prop_name为ro.hardware. sensors,如果该属性存在,则用prop存储属性值,并判断HAL_LIBRARY_PATH2或HAL_LIBRARY_PATH1中是否存在模块sensors.prop.so;存在对应的模块,则跳到found;

3, 如果ro.hardware. sensors不存在,或者属性存在,但模块sensors.prop.so 不存在,则依次扫描variant_keys 这个数组中的属性是否存在,如果存在,则判断模块sensors.prop.so是否存在,一旦存在,则立马退出循环,跳到found; 这里variant_keys 数组,有4 个成员,  “ro.hardware”、“ ro.product.board”、“ ro.board.platform”、“ ro.arch”。系统会通过适当的方法,根据平台、架构等给这些属性赋值,“ro.hardware”属性的属性值是在系统启动时由init 进程负责设置的。它首先会读取/proc/cmdline文件,检查里面有没有一个名为androidboot.hardware的属性,该属性在BoardConfig.mk 文件中有定义,如果有,就把它的值赋值给“ro.hardware”,高通平台即为qcom;“ ro.product.board”、“ ro.board.platform”、“ ro.arch” 属性是从/system/build.prop 文件读取出来的, 这里ro.product.board=msm8916(BoardConfig.mk  中定义了TARGET_BOARD_PLATFORM=

msm8916);/system/build.prop文件是由编译系统中的编译脚本build/core/Makefile和shell脚本build/tools/buildinfo.sh生成的,这里不再详细分析。

4, 本例中ro.product.board的属性为8916,hw_module_exists函数判断sensors.msm8916.so存在,并把模块完整路径赋值给path,然后跳到found执行中加载模块库的函数load,load 会加载path指定的模块,并从模块中获取名为HMI的变量

hw_get_module方法如下,

int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
这是标准的Android HAL接口,所有HAL模块的加载和模块变量的获取都是调用这个函数,通过指定的模块id 来指定模块.
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值