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 ...
随机推荐
- 某个灰产远程调用的script源码
访问一个老域名,可能是释放了被所灰产的的注册了,跳转简单扒下他们的源码. 主要是三段script代码,第一段是百度自动推送代码,第二段是站长统计代码,第三段则是远程调用断码. <html xml ...
- 快速搭建一个spring cloud 子模板--好记性不如烂笔头
建 application.yml 文件 server: # 服务端口号 port: 7609spring: application: # 服务名称 - 服务之间使用名称进行通讯 name: serv ...
- MongoDB 副本集(Replica Set)
副本集(Replica Set) 副本集概念 此集群拥有一个主节点(Master)和多个从节点(Slave),与主从复制模式类似,但是副本集与主从复制的区别在于:当集群中主节点发生故障时,副本集可以自 ...
- 解决vue 移动端项目“切换页面,页面置顶”后报错为:"TypeError: Cannot set property 'scrollTop' of null"
参考原代码链接:https://www.cnblogs.com/wayneliu007/p/11932204.html 报错截图: 解决方法: 导入的getScrollParent为真返回的null ...
- Python pdb模块的使用
野路子出生,写Python也有段时间了,一般的调试都用的print, PyCharm的debug功能也用的比较少,主要一般也用不到,第二是自己也不怎么会用. 服务器开发,本地根本没有运行的环境,前面学 ...
- ElasticSeach性能调优
1. 硬件相关 1.1 硬盘 一块好的硬盘,会带来ES整体性能10倍以上提升,推荐在datanode节点上使用SSD硬盘,索引的data目录,存放在SSD硬盘上. 1.2 内存 建议内存>128 ...
- java中数组操作,正序,逆序,子数组、自定义排序
// 数组定义,初始化 int[] array = new int[]{1, 2, 2, 1}; int[] dest = new int[10]; Integer[] soul = new Inte ...
- gcc的编译过程
1. 预处理,生成 .i 的文件.(input) 2. 将 .i的文件转换成汇编语言,生成 .s 的文件 3.生成机器语言文件,.o的文件 4.连接目标代码,生成可执行文件 .out
- centos7(虚拟机)下安装redis
centos7(虚拟机)下安装redis 安装 下载redis安装包 wget https://download.redis.io/releases/redis-6.2.1.tar.gz 解压安装包 ...
- 问题记录[ PPOME 修改子屏幕日期弹框,No changes to data, periods undone. Message no. 5A496 ]
最近在做组织信息增强,将子屏幕嵌入PPOME后,修改日期后会弹出信息框并重置300屏幕的开始日期.且PO13和PP01无异常 刚开始以为7000屏幕配置问题,但是对比后并没发现异常.跟踪消息号发现函数 ...