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 ...
随机推荐
- crontab执行不生效
背景:不知道什么原因脚本手动执行:正常:crontab执行不生效: 1.将命令所属路径加入到 /etc/crontab中, 2.在shell脚本中加入 source /etc/profile
- vue仿QQ聊天室|vue聊天实例,直播聊天室
图片压缩 百亿站点 基于vue2.0+vue-cli+vuex+vue-router+webpack+es6+wcPop等技术开发的仿微信聊天界面|仿微信聊天室vue-chatRoom,实现了微信聊天 ...
- Pytest Fixture(三)
name: name参数表示可以对fixture的名称进行重命名: 注意:通过name重命名后,继续使用以前的名字调用会报错. import pytest @pytest.fixture(name=' ...
- sqlmap-1.6.12.11
Usage: sqlmap.py [options] 选项: -h, --help 显示基本帮助信息并退出 -hh 显示高级帮助信息并退出 --version 显示程序的版本号并退出 -v VERBO ...
- luogu 4886
点分治好题 统计距离正常点分治统计即可,我们只需考虑何时达到最优 有两种情况: 第一:代价最大的询问两个端点在不同的两个子树中 因为这种情况下,无论根向那个子树移动都会等价地增加到达另一个端点的代价, ...
- Flutter在iOS中一些点
1. ios对Flutter有如下依赖 Flutter.framework: Flutter engine等: APP.framework:业务代码, 由dart代码生成.App.framew ...
- Windows开机自动运行.bat文件
方法/步骤:一:打开我的电脑, 在地址栏输入:"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup" 二,把自 ...
- Windows 10 ~ Docker 安装
Windows安装Docker 不推荐在Windows系统安装Docker,会有一些奇怪的坑不容易解决,建议windows环境安装虚拟机,通过虚拟机中的Linux系统安装Docker 官方安装文档 9 ...
- Word技巧:ALT+X快捷键
Word技巧:ALT+X快捷键 在Word中输入数字,然后使用键盘快捷键「ALT + X」,即可快速生成一个文字图形. 部分数字的对比参照: 2564 ╤ 2582 ▂ 2600 2618 ☘ 256 ...
- Kafka相关问题
Kafka有哪几个部分组成 生产者.消费者.topic.group.partition kafka的group1)定义:即消费者组是 Kafka 提供的可扩展且具有容错性的消费者机制.在Kafka中, ...