2019独角兽企业重金招聘Python工程师标准>>>

大家都知道android是基于linux的kernel上的。android可以 运行在intel,高通,nvidia等硬件平台。但是涉及到一些GPU,显卡和一些设备的驱动问题,因为这些驱动都不是开源的,google位了兼容这些设备厂商的驱动源码,提出了硬件抽象层HAL的概念。HAL层对上为framework和native开发提供统一的API接口,为下层驱动的代码提供统一的调用接口。本文主要讲解HAL是如何实现的。

1.HAL的数据结构

HAL的通用写法里面有两个重要的结构体:

1.1 hw_module_t 硬件模块结构体

typedef struct hw_module_t {/** tag must be initialized to HARDWARE_MODULE_TAG */uint32_t tag;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;/** padding to 128 bytes, reserved for future use */uint32_t reserved[32-7];} hw_module_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;

模块方法的结构体,open的函数指针,用于打开一个硬件设备hw_device_t。开发者需要实现这个open函数。

1.2硬件设备结构体

typedef struct hw_device_t {/** tag must be initialized to HARDWARE_DEVICE_TAG */uint32_t tag;uint32_t version;/** reference to the module this device belongs to */struct hw_module_t* module;/** padding reserved for future use */uint32_t reserved[12];/** Close this device */int (*close)(struct hw_device_t* device);} hw_device_t;

表示一个硬件抽象设备。这是通用的结构体,开发者可以继承这个结构体添加自己需要的接口。

1.3 获取一个hw_model_t模块

HAL层提供一个方法用户获取一个model,进而同过open方法打开设备device

/*** Get the module info associated with a module by id.** @return: 0 == success, <0 == error and *module == NULL*/
int hw_get_module(const char *id, const struct hw_module_t **module);

定义一个全局变量

const struct hw_module_t   HAL_MODULE_INFO_SYM={ ...};

用于在hw_get_modules通过解析so时,得到该全局变量。

2.硬件模块库的装载于解析
装载和解析有hw_get_module 完成,它会安按照一定的规则去查找so库,然后解析出全局变量名,得到硬件设备的open函数,最后通过参数返回一个device的指针给调用者。

2.1搜索so的规则;

/** Base path of the hal modules */
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"/*** 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 differentfile on the emulator. */"ro.product.board","ro.board.platform","ro.arch"
};

搜索规则就是按照上面的说明进行。

2.2函数加载解析的过程

(1)调用hw_get_module,通过传给他一个module_id 字符串例如“camera”等。调用hw_get_module_by_class(id, NULL, module);

(2)搜索对应的so并调用load去解析so

int hw_get_module_by_class(const char *class_id, const char *inst,const struct hw_module_t **module)
{int status = -EINVAL;int i = 0;char prop[PATH_MAX] = {0};char path[PATH_MAX] = {0};char name[PATH_MAX] = {0};if (inst)snprintf(name, PATH_MAX, "%s.%s", class_id, inst);elsestrlcpy(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.*//* Loop through the configuration variants looking for a module */for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {if (i < HAL_VARIANT_KEYS_COUNT) {if (property_get(variant_keys[i], prop, NULL) == 0) {continue;}snprintf(path, sizeof(path), "%s/%s.%s.so",HAL_LIBRARY_PATH2, name, prop);if (access(path, R_OK) == 0) break;snprintf(path, sizeof(path), "%s/%s.%s.so",HAL_LIBRARY_PATH1, name, prop);if (access(path, R_OK) == 0) break;} else {snprintf(path, sizeof(path), "%s/%s.default.so",HAL_LIBRARY_PATH2, name);if (access(path, R_OK) == 0) break;snprintf(path, sizeof(path), "%s/%s.default.so",HAL_LIBRARY_PATH1, name);if (access(path, R_OK) == 0) break;}}status = -ENOENT;if (i < HAL_VARIANT_KEYS_COUNT+1) {/* load the module, if this fails, we're doomed, and we should not try* to load a different variant. */status = load(class_id, path, module);}return status;
}

(3)load函数解析so,得到hw_module_t的hw_device_t的函数指针。

/*** 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*/handle = dlopen(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;}/* 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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://my.oschina.net/xcy2011sky/blog/492652

Android的Framework分析---4硬件抽象HAL相关推荐

  1. Android GNSS 模块分析(四)HAL 层

    紧接着上一篇(Android GNSS 模块分析(三)JNI 层),继续来分析下 Android GNSS HAL 层的功能,本篇准备先介绍下 HIDL 层的封装.至于后面的 HAL 层的功能,由于使 ...

  2. Android GNSS 模块分析(五)NMEA 协议

    紧接着上一篇<Android GNSS 模块分析(四)HAL 层>,本篇简述下导航硬件设备与卫星导航系统之间的通信协议. NMEA 协议 简介: NMEA(National Marine ...

  3. Android架构实例分析之编写hello驱动的HAL层代码

    Android架构实例分析之编写hello驱动的HAL层代码 摘要: HAL层中文名称又叫硬件抽象层,可以理解我Linux驱动的应用层.本文实现了一个简单的hello HAL的代码,衔接hello驱动 ...

  4. 【Android 10 源码】healthd 模块 HAL 1.0 分析

    health@1.0:android.hardware.health@1.0 的缩写.指的是 Android 8.0 中发布的运行状况 HIDL 的 1.0 版 HAL. Android 8.x 中的 ...

  5. 【Android 10 源码】healthd 模块 HAL 2.0 分析

    Android 9 引入了从 health@1.0 HAL 升级的主要版本 android.hardware.health HAL 2.0.这一新 HAL 具有以下优势: 框架代码和供应商代码之间的区 ...

  6. 如何在Android Framework中添加自定义硬件编解码器?

    原文:How to add custom hardware codec to Android Framework? http://gopinaths.gitlab.io/post/custom_har ...

  7. Android源码分析 - Framework层的Binder(客户端篇)

    开篇 本篇以aosp分支android-11.0.0_r25作为基础解析 我们在之前的文章中,从驱动层面分析了Binder是怎样工作的,但Binder驱动只涉及传输部分,待传输对象是怎么产生的呢,这就 ...

  8. idcardweb装入失败_vpk安装错误0xffffe Android Crash问题分析以及解决 - 硬件设备 - 服务器之家...

    vpk安装错误0xffffe Android Crash问题分析以及解决 发布时间:2017-04-10 来源:服务器之家 1.问题介绍 Crash问题,无论是java侧还是native侧,在日常测试 ...

  9. Android 源码分析

    查看源码版本号: build\core\version_defaults.mk //搜索该文件中的 PLATFORM_VERSION值 frameworks 目录 (核心框架--java及C++语言) ...

最新文章

  1. 8位无符号和8位有符号转化为更高字节类型的问题
  2. Parser in C
  3. Feature Selection Techniques
  4. getHibernateTemplate()和getSession()的区别
  5. Python学习笔记:SMTP服务器
  6. VMware Workstation与VMware vSphere的区别
  7. as和java什么关系_深入理解happens-before和as-if-serial语义
  8. php 图片剪切为透明,解决PHP剪切缩略图生成png,gif透明图时,黑色背景问题
  9. scala学习笔记(四)样本类与模式匹配
  10. Flutter直播间弹幕效果实现
  11. C语言之实用调试技巧
  12. unordered_set使用介绍
  13. 第七篇章——垃圾回收概念及相关算法
  14. C# 打印预览 PrintDocument打印、打印预览
  15. 【SSL】1758连通图
  16. 一份非常适合收藏的Android进阶面试题!附面试题答案
  17. HNUST--2187 最小生成树(邻接矩阵或邻接表)
  18. 均值、中值、标准差、四分位差(C++)
  19. python 新闻摘要_每日新闻摘要:iPad Mini评论,AT&T首席执行官获得Robocall等等
  20. 02pysal距离权重矩阵

热门文章

  1. ftp 信息服务器日常维护,Web Ftp Mail服务器的日常管理与维护
  2. CF1038D Slime 构造
  3. vs2017的一件奇葩事
  4. 2017/10/12 表格与表单
  5. Tricky Sum
  6. lncRNA研究利器之TANRIC
  7. HDU 1043 Eight(双向BFS+康托展开)
  8. Linux文件合并去重
  9. 进击的UI--------------------GETPOST
  10. WPF oxyPlot 使用总结