HAL层分析
1. 安卓HAL模块基本
2. 定义hal层代码的5个特性
1)硬件抽象层具有与硬件的密切相关性。
2) 硬件抽象层具有与操作系统无关性。
3) 接口定义的功能应该包含硬件或者系统所需硬件支持的所有功能。
4) 接口简单明了,太多接口函数会增加软件模拟的复杂性。
5) 具有可预测的接口设计有利于系统的软、硬件测试和集成。
3. 安卓中hal层相关目录
1)libhardware_legacy :过去的目录,采取链接库模块观念来架构
2)libhardware: 新版的目录,被调整为用HAL stub 观念来架构
3)ril: 是Radio 接口层
4)msm7k : 和QUAL 平台相关的信息
4. hal module基本介绍
4.1 hal module有3个结构体
4.1.1 struct hw_module_t
/*
- Value for the hw_module_t.tag field
*/
define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))
define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')
/**
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.
/
typedef struct hw_module_t {
/* tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;/**
- The API version of the implemented module. The module owner is
- responsible for updating the version when a module interface has
- changed.
- The derived modules such as gralloc and audio own and manage this field.
- The module user must interpret the version field to decide whether or
- not to inter-operate with the supplied module implementation.
- For example, SurfaceFlinger is responsible for making sure that
- it knows how to manage different versions of the gralloc-module API,
- and AudioFlinger must know how to do the same for audio-module API.
- The module API version should include a major and a minor component.
- For example, version 1.0 could be represented as 0x0100. This format
- implies that versions 0x0100-0x01ff are all API-compatible.
- In the future, libhardware will expose a hw_get_module_version()
- (or equivalent) function that will take minimum/maximum supported
- versions as arguments and would be able to reject modules with
- versions outside of the supplied range.
*/
uint16_t module_api_version;
define version_major module_api_version
/**
* version_major/version_minor defines are supplied here for temporary
* source code compatibility. They will be removed in the next version.
* ALL clients must convert to the new version format.
*/
/**
* The API version of the HAL module interface. This is meant to
* version the hw_module_t, hw_module_methods_t, and hw_device_t
* structures and definitions.
*
* The HAL interface owns this field. Module users/implementations
* must NOT rely on this value for version information.
*
* Presently, 0 is the only valid value.
*/
uint16_t hal_api_version;
define version_minor hal_api_version
/** 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 */
void* dso;
ifdef LP64
uint64_t reserved[32-7];
else
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
endif
} hw_module_t;
- 从hw_module_t 注释可以看出,每个硬件抽象层模块都必须有一个名称为 HAL_MODULE_INFO_SYM 的结构体,且这个结构体的第一个字段必须是hw_module_t
- hw_module_t.tag 的值必须是 HARDWARE_MODULE_TAG ,即(H) << 24) | ((W) << 16) | ((M) << 8) | (T) ,用来标识硬件抽象层模块结构体。
- hw_module_t.methods定义了一个硬件抽象层模块的操作列表
4.1.2 struct hw_modulemethods_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 只有一个函数指针成员变量,用来打开硬件抽闲层模块中的硬件设备。
2)成员变量的参数module表示要打开的硬件设备所在模块;
3)成员变量的参数id表示要打开的硬件设备的ID;
4)成员变量的参数device是一个输出参数,用来描述一个已经打开的硬件设备。struct hw_device_t
define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')
/**
Every device data structure must begin with hw_device_t
followed by module specific public methods and attributes.
/
typedef struct hw_device_t {
/* tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;/**
- Version of the module-specific device API. This value is used by
- the derived-module user to manage different device implementations.
- The module user is responsible for checking the module_api_version
- and device version fields to ensure that the user is capable of
- communicating with the specific module implementation.
- One module can support multiple devices with different versions. This
- can be useful when a device interface changes in an incompatible way
- but it is still necessary to support older implementations at the same
- time. One such example is the Camera 2.0 API.
- This field is interpreted by the module user and is ignored by the
- HAL interface itself.
*/
uint32_t version;
/** reference to the module this device belongs to /
struct hw_module_t module;/** padding reserved for future use */
ifdef LP64
uint64_t reserved[12];
else
uint32_t reserved[12];
endif
/** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t;
1)从hw_device_t 注释可以看出硬件抽象层模块的每一个硬件设备都必须自定义一个硬件设备结构体,且他的第一个成员变量的类型必须是hw_device_t。
2)hw_device_t.tag 的值必须是 **HARDWARE_DEVICE_TAG ** ,即(H) << 24) | ((W) << 16) | ((D) << 8) | (T) ,用来标识硬件抽象中的硬件设备结构体。
3)结构体hw_device_t 的成员变量close是一个函数指针,它用来关闭一个硬件设备。
4.1.4
4.2 hal module有两个变量
4.3 hal module有一个函数接口
函数hw_get_module()。
5. hal源码分析
5.1 hardware.c
5.1.1 hal模块文件命名规范
define LOG_TAG "HAL"
/** Base path of the hal modules */
if defined(LP64)
define HAL_LIBRARY_PATH1 "/system/lib64/hw"
define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
define HAL_LIBRARY_PATH3 "/odm/lib64/hw"
else
define HAL_LIBRARY_PATH1 "/system/lib/hw"
define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
define HAL_LIBRARY_PATH3 "/odm/lib/hw"
endif
/**
- 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. */ //emulator : 仿真器;pick up :获取
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
- 硬件抽象模块文件的命名规范为“<MODULE_ID>.variant.so”,其中MODULE_ID 标识模块的ID,variant 表示四个系统属性 ro.hardware、ro.product.board、ro.board.platform、ro.arch之一。
- 系统在加载硬件抽象层模块时,依次按照 ro.hardware.MODULE_ID、ro.hardware、ro.product.board、ro.board.platform、ro.arch的顺序来取他们的属性值。
- 如果其中一个系统属性存在,那么就把它的值作为variant的值,然后在检查对应的文件是否存在,如果存在,那么就找到要加载的硬件抽象层文件了;
- 如果四个属性都不存在,或者四个属性对应的系统硬件抽象层文件不存在,就是用 “<MODULE_ID>.default.so” 来作为要加载的硬件抽象层模块文件的名称
static const int HAL_VARIANT_KEYS_COUNT =
(sizeof(variant_keys)/sizeof(variant_keys[0]));
/**
Load the file defined by the variant and if successful
return the dlopen handle and the hmi.
@return 0 = success, !0 = failure.
*/
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status = -EINVAL;
void *handle = NULL;
struct hw_module_t *hmi = NULL;/*
- load the symbols resolving undefined symbols before
- dlopen returns. Since RTLD_GLOBAL is not or'd in with
- RTLD_NOW the external symbols will not be global
/
if (strncmp(path, "/system/", 8) == 0) {
/ If the library is in system partition, no need to check- sphal namespace. Open it with dlopen.
*/
handle = dlopen(path, RTLD_NOW);
} else {
handle = android_load_sphal_library(path, RTLD_NOW);
}
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
- sphal namespace. Open it with dlopen.
/* 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);
if (hmi == NULL) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}hmi->dso = handle;
/* success */
status = 0;done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}*pHmi = hmi;
return status;
}
/*
Check if a HAL with given name and subname exists, if so return 0, otherwise
otherwise return negative. On success path will contain the path to the HAL.
*/
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_PATH3, name, subname);
if (access(path, R_OK) == 0)
return 0;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;
}
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Loop through the configuration variants looking for a module */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Nothing found, try the default */
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
found:
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
return load(class_id, path, module);
}
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
HAL层分析的更多相关文章
- Android中基于CGroup的memory子系统HAL层分析-lmkd
Android在内存管理上于Linux有些小的区别,其中一个就是引入了lowmemorykiller.从lowmemorykiller.c位于drivers/staging/android也可知道,属 ...
- Android Hal层简要分析
Android Hal层简要分析 Android Hal层(即 Hardware Abstraction Layer)是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次, ...
- ZT Android4.2关于bluetooth在HAL层的分析(1)
我的电子杂烩饭 http://blog.sina.com.cn/wuchuchu2012 [订阅][手机订阅] 首页 博文目录 图片 关于我 正文 字体大小:大 中 小 Android4.2关于blu ...
- 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一
作者:唐老师,华清远见嵌入式学院讲师. 1. Sensor的概念 Sensor即传感器,在当前智能手机上大量存在:G-Sensor.LightsSensor. ProximitySensor.Temp ...
- Android HAL层与Linux Kernel层驱动开发简介
近日稍微对Android中的驱动开发做了一些简要的了解. HAL:Hardware Abstract Layer 硬件抽象层,由于Linux Kernel需要遵循GPL开源协议,硬件厂商为了保护自己硬 ...
- Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务
有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...
- 如何在 kernel 和 hal 层读取同一个标志
很多时候我们需要从 HAL 层(Hardware Abstract Layer)传一个标志给 kernel 层.一般这种传递是不能直接通过定义全局变量来实现的. 此时可以通过读写文件来实现该标志. 譬 ...
- 高通HAL层之Sensor HAL
高通的HAL层其实分为两种,一种是直接从kernel这边报数据上来的,由sensor HAL层来监听,另一种是走ADSP的模式,HAL层是通过qmi的形式进行监听的: 走ADSP架构的可以看下面的博客 ...
- 【Android】Sensor框架HAL层解读
Android sensor构建 Android4.1 系统内置对传感器的支持达13种,他们分别是:加速度传感器(accelerometer).磁力传感器(magnetic field).方向传感器( ...
- 〖Android〗OK6410a的Android HAL层代码编写笔记
一.编写LED灯的Linux驱动程序代码 之所以使用存在HAL层,是为了保护对硬件驱动过程的逻辑与原理: 所以,残留在Linux驱动层的代码,只保留了基本的读写操作,而不含有关键的逻辑思维: 1. l ...
随机推荐
- FIFO 串口接收处理机制
与安富莱电子的串口处理机制做对比交互 参考链接: https://www.eet-china.com/mp/a161019.html
- Java流程控制之for循环
for循环[重点] 虽然所有的循环结构都可以用while或者do...while表示,但Java提供了另一种语句--for循环,使一些循环结构变得更加简单. for循环语句是支持迭代的一种通用结构,是 ...
- Unity 消息机制
最近有新项目需要和同事合作开发,他做UI 我做网络层,做着做着发现 如果我们要相对独立完成自己的开发任务,那我们的代码耦合得减少,不然 一个人代码有大改的时候,另一个人也要进行大幅修改,这样不便于后期 ...
- 解决windows的mysql无法启动 服务没有报告任何错误的经验。
解决windows的mysql无法启动 服务没有报告任何错误的经验. 相信很多人都遇到过安装Mysql的时候出现各种各样的问题,教大家解决window下mysql服务没有报告任何错误的情况下无法启动 ...
- MySQL8.0的下载、安装、配置
转1: MySQL8.0的下载.安装.配置 MySQL8安装教程(下载.安装.连接.卸载) Navicat Premium 15激活(含注册机)
- Ajax的两种写法
先写一串数据 1 { 2 "status": 200, 3 "data": { 4 "name": "web211001" ...
- js判断变量数据类型typeof、instanceof、Object.prototype.toString.call()、 constructor
JavaScript有4种方法判断变量的类型,分别是typeof.instanceof.Object.prototype.toString.call()(对象原型链判断方法). constructor ...
- 第一讲:selenium快速入门
一.selenium目前住主流的web自动化测试框架: 1.资料丰富 资料丰富 2.测试岗位招聘要求,上板率非常之高 3.支持多语言(iava/ pythan/ go /js) ...
- 【pytest】pytest.mark.dependency用例依赖标签,并解决依赖失效的问题
pytest第三方插件,用来解决用例之间的依赖关系.如果依赖的用例执行失败后 后续的用例会被跳过执行,相当于智能执行了pytest.mark.skip, 首先要安装插件:pip install pyt ...
- Arthas 查询服务器内存数据
1.打开Arthas所在位置 eg:/home 2.java -jar arthas-boot.jar 运行jar包 3.选择要执行的java jar包 eg : 1 4.执行查看命令vmtool - ...