Android HAL模块实现
1. HAL介绍
Android的HAL(Hardware Abstract Layer硬件抽象层)是为了保护一些硬件提供商的知识产权而提出的。是为了避开linux的GPL束缚。
思路是把控制硬件的动作都放到了Android HAL中,而linux driver仅仅完毕一些简单的数据交互作用,甚至把硬件寄存器空间直接映射到user space。而Android是基于Aparch的license,因此硬件厂商能够仅仅提供二进制代码,所以说Android仅仅是一个开放的平台,并非一个开源的平台。
总结下来,Android HAL存在的原因主要有:
- 并非全部的硬件设备都有标准的linux kernel的接口
- KERNEL DRIVER涉及到GPL的版权。
某些设备制造商并不原因公开硬件驱动,所以才去用HAL方式绕过GPL。
- 针对某些硬件,Android有一些特殊的需求。
- 不同的平台厂商可在遵循HAL调用接口的前提下实现自己的HAL,不会影响到上层的调用者,这样减少了模块间的耦合度,能够让平台开发人员仅仅关心HAL本身的实现就可以。
下图是HAL在android系统中所处的位置:
从这张图中能够看出,HAL把内核和framework隔离开来,使上层的开发能够不依赖内核与驱动的实现。在android源代码中,HAL大致位于以下几个位置:
- libhardware_legacy/ - 旧的架构、採取链接库模块的模式进行。
- libhardware/ - 新架构、调整为 HAL stub 的概念。
- ril/ - Radio Interface Layer。
- msm7k QUAL平台相关。
主要包括下面一些模块:Gps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Gralloc等。
2. HAL的两种实现方式
下图分别为旧的HAL实现与新的HAL实现框图:
libhardware_legacy 是将 *.so 文件当作shared library来使用,在runtime(JNI 部份)以 direct function call 使用 HAL module。通过直接函数调用的方式,来操作驱动程序。
当然,应用程序也能够不须要通过 JNI 的方式进行,直接载入 *.so (dlopen)的做法调用*.so 里的符号(symbol)也是一种方式。总而言之是没有经过封装,上层能够直接操作硬件。
现 在的 libhardware 作法。就有「stub」的味道了。HAL stub 是一种代理人(proxy)的概念,stub 尽管仍是以 *.so檔的形式存在,但 HAL 已经将 *.so 档隐藏起来了。
Stub 向 HAL「提供」操作函数(operations)。而 runtime 则是向 HAL 取得特定模块(stub)的 operations。再 callback 这些操作函数。这样的以 indirect function call 的实作架构。让HAL stub 变成是一种「包括」关系,即 HAL 里包括了许很多多的
stub(代理人)。Runtime 仅仅要说明「类型」。即 module ID,就能够取得操作函数。对于眼下的HAL,能够觉得Android定义了HAL层结构框架,通过几个接口訪问硬件从而统一了调用方式。
由上可大致看出这两种实现方式的优劣:
HAL_legacy方式的HAL是一个模块,採用共享库形式,在编译时会调用到。因为採用function call形式调用,因此可被多个进程使用。但会被mapping到多个进程空间中,造成浪费,同一时候须要考虑代码是否能安全重入的问题(thread safe)。而新式的HAL採用HAL module和HAL stub结合形式,HAL stub不是一个share library,编译时上层仅仅拥有訪问HAL stub的函数指针,并不须要HAL stub。
上层通过HAL module提供的统一接口获取并操作HAL stub,so文件仅仅会被mapping到一个进程,也不存在反复mapping和重入问题。
3. HAL模块的结构与编写方法
HAL模块主要有二个结构:
struct hw_module_t-代表抽象硬件模块,包括硬件模块的一些基本信息,比如版本,开发人员等,另一个成员函数结构体。
struct hw_module_methods_t ,里面仅仅有一个用于打开抽象硬件设备hw_device_t的open函数指针。
struct hw_device_t-代表抽象硬件设备。里面包括了版本。一个关闭硬件的close函数指针,以及一个指向hw_module_t的结构的指针。
这两个结构的定义在hardware/libhardware/include/hardware/hardware.h里面。在实现自己的hw module与hw device结构时,第一个成员变量必须是这两个结构。以达到类似C++中的继承的目的。
这两个结构的定义例如以下所看到的:
- 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 */
- <strong> struct hw_module_methods_t* methods;</strong>
- /** module's dso */
- <strong> void* dso;</strong>
- /** 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;
- /**
- * 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 */
- <strong>struct hw_module_t* module;</strong>
- /** padding reserved for future use */
- uint32_t reserved[12];
- /** Close this device */
- <strong>int (*close)(struct hw_device_t* device);</strong>
- } hw_device_t;
4. 硬件模块库的使用
硬件模块库的装载与解析由hardware.c中的hw_get_module函数完毕,它先依照一定的规则选择然后载入硬件模块库,然后由HAL_MODULE_INFO_SYM解析出库中的全局变量名。得到硬件模块库指针(hw_module_t结构)。然后返回给调用者。
以下以camera为样例来说明怎样使用HAL层。
在系统启动创建CameraService对象时。其函数onFirstRef被调用,在它里面,通过hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t**)&mModule)函数获取camera的抽象硬件模块camera_module。其过程如上所说,通过Camera的HAL动态库然后解析HAL_MODULE_INFO_SYM符号得到全局变量,然后通过获取到的抽象硬件模块结构获取系统拥有的Camera数量等。详细代码參见CameraService.cpp。
当中camera_module即camera HAL的抽象硬件模块。其定义例如以下(camera_common.h):
- typedef struct camera_module {
- hw_module_t common;
- /**
- * get_number_of_cameras:
- *
- * Returns the number of camera devices accessible through the camera
- * module. The camera devices are numbered 0 through N-1, where N is the
- * value returned by this call. The name of the camera device for open() is
- * simply the number converted to a string. That is, "0" for camera ID 0,
- * "1" for camera ID 1.
- *
- * The value here must be static, and cannot change after the first call to
- * this method
- */
- int (*get_number_of_cameras)(void);
- /**
- * get_camera_info:
- *
- * Return the static camera information for a given camera device. This
- * information may not change for a camera device.
- *
- */
- int (*get_camera_info)(int camera_id, struct camera_info *info);
- /**
- * set_callbacks:
- *
- * Provide callback function pointers to the HAL module to inform framework
- * of asynchronous camera module events. The framework will call this
- * function once after initial camera HAL module load, after the
- * get_number_of_cameras() method is called for the first time, and before
- * any other calls to the module.
- *
- * Version information (based on camera_module_t.common.module_api_version):
- *
- * CAMERA_MODULE_API_VERSION_1_0, CAMERA_MODULE_API_VERSION_2_0:
- *
- * Not provided by HAL module. Framework may not call this function.
- *
- * CAMERA_MODULE_API_VERSION_2_1:
- *
- * Valid to be called by the framework.
- *
- */
- int (*set_callbacks)(const camera_module_callbacks_t *callbacks);
- /**
- * get_vendor_tag_ops:
- *
- * Get methods to query for vendor extension metadata tag information. The
- * HAL should fill in all the vendor tag operation methods, or leave ops
- * unchanged if no vendor tags are defined.
- *
- * Version information (based on camera_module_t.common.module_api_version):
- *
- * CAMERA_MODULE_API_VERSION_1_x/2_0/2_1:
- * Not provided by HAL module. Framework may not call this function.
- *
- * CAMERA_MODULE_API_VERSION_2_2:
- * Valid to be called by the framework.
- */
- void (*get_vendor_tag_ops)(vendor_tag_ops_t* ops);
- /* reserved for future use */
- void* reserved[8];
- } camera_module_t;
由其定义看到,其第一个成员为hw_module_t common,即上面说的自己的硬件抽象模块必须包括hw_module结构。达到“继承”的目的。另外定义了几个自己的成员变量,比方获取camera个数。及camera信息等。
使用hw_get_module获取到的camera_module_t变量位于平台的camera HAL实现库中。不同的厂家可能文件名称字有所不同,可是肯定会实现以下类似的结构(CameraHAL.cpp)。
- camera_module_t HAL_MODULE_INFO_SYM __attribute__ ((visibility("default"))) = {
- common : {
- tag : HARDWARE_MODULE_TAG,
- module_api_version : CAMERA_MODULE_API_VERSION_2_0,
- hal_api_version : HARDWARE_HAL_API_VERSION,
- id : CAMERA_HARDWARE_MODULE_ID,
- name : "Default Camera HAL",
- author : "The Android Open Source Project",
- methods : &gCameraModuleMethods,
- dso : NULL,
- reserved : {0},
- },
- get_number_of_cameras : get_number_of_cameras,
- get_camera_info : get_camera_info,
- set_callbacks : set_callbacks
- };
有了Camera的HAL层的硬件抽象模块camera_module。就能够通过camera_module获取到硬件抽象设备camera_device_t。只是它封装在CameraHardwareInterface中,在连接一个camera时(CameraService的connect函数,最后调到CameraClient::initialize)。将先创建CameraHardwareInterface对象,然后在其初始化函数中得到camera_device_t:int rc = module->methods->open(module,
mName.string(), (hw_device_t **)&mDevice);这个open函数就是gCameraModuleMethods里面的open函数,事实上现例如以下所看到的:
- int Camera::open(const hw_module_t *module, hw_device_t **device)
- {
- ALOGI("%s:%d: Opening camera device", __func__, mId);
- CAMTRACE_CALL();
- pthread_mutex_lock(&mMutex);
- if (mBusy) {
- pthread_mutex_unlock(&mMutex);
- ALOGE("%s:%d: Error! Camera device already opened", __func__, mId);
- return -EBUSY;
- }
- // TODO: open camera dev nodes, etc
- mBusy = true;
- mDevice.common.module = const_cast<hw_module_t*>(module);
- *device = &mDevice.common;
- pthread_mutex_unlock(&mMutex);
- return 0;
- }
这里面就返回了camera_device_t,而此结构的初始化在构造函数中:
- </pre>
- <pre>Camera::Camera(int id)
- : mId(id),
- mStaticInfo(NULL),
- mBusy(false),
- mCallbackOps(NULL),
- mStreams(NULL),
- mNumStreams(0),
- mSettings(NULL)
- {
- pthread_mutex_init(&mMutex, NULL);
- pthread_mutex_init(&mStaticInfoMutex, NULL);
- memset(&mDevice, 0, sizeof(mDevice));
- mDevice.common.tag = HARDWARE_DEVICE_TAG;
- mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0;
- mDevice.common.close = close_device;
- mDevice.ops = const_cast<camera3_device_ops_t*>(&sOps);
- mDevice.priv = this;
- }
至此,CameraService就得到了Camera的HAL层的硬件抽象模块camera_module_t和抽象设备camera_device_t。有了这两个结构,上层就能够使用camera的功能了。以上代码基于android4.4/hardware/libhardware/modules/camera,使用的是c++的方式实现。不同硬件厂家的实现方式可能不同。但同样的是都必须实现这两个结构。
5. 总结
- HAL通过hw_get_module来获取hw_module_t结构。
- HAL通过hw_module_t->methods->open获取hw_device_t指针,并在在open中初始化hw_device_t中的结构。包含函数指针(close操作)等。
- 两个重要结构:
hw_module_t:硬件抽象模块,能够用hw_get_module获取到。
当中又包括了一个hw_module_methods_t结构,当中定义了打开设备open方法。
hw_device_t:硬件抽象设备。主要定义了硬件相关的一些函数。參数等。此结构通过hw_module_methods_t里面定义的open函数获取。
以上大致就是android hal模块的内容,下一篇会以android的一个重要的HAL模块gralloc来看看其详细的实现。
关注微信公众平台:程序猿互动联盟(coder_online)。你能够第一时间获取原创技术文章。和(java/C/C++/Android/Windows/Linux)技术大牛做朋友,在线交流编程经验,获取编程基础知识。解决编程问题。程序猿互动联盟,开发者自己的家。
Android HAL模块实现的更多相关文章
- Android架构分析之使用自定义硬件抽象层(HAL)模块
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:2.3.7_r1 Linux内核版本:android-goldfish-2.6.29 在上一篇博 ...
- android HAL 教程(含实例)
http://www.cnblogs.com/armlinux/archive/2012/01/14/2396768.html Android Hal 分析 ...
- 【转】Android HAL实例解析
原文网址:http://www.embedu.org/Column/Column339.htm 作者:刘老师,华清远见嵌入式学院讲师. 一.概述 本文希望通过分析台湾的Jollen的mokoid 工程 ...
- Android Hal 分析
本文是基于android4.0.3.对应其他低版本的代码,可能有所差异,但基本大同小异. Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚.思路是把控 ...
- 〖Android〗OK6410a的Android HAL层代码编写笔记
一.编写LED灯的Linux驱动程序代码 之所以使用存在HAL层,是为了保护对硬件驱动过程的逻辑与原理: 所以,残留在Linux驱动层的代码,只保留了基本的读写操作,而不含有关键的逻辑思维: 1. l ...
- Android HAL实例解析
一.概述 本文希望通过分析台湾的Jollen的mokoid 工程代码,和在s5pc100平台上实现过程种遇到的问题,解析Andorid HAL的开发方法. 二.HAL介绍 现有HAL架构由Patric ...
- <Android HAL 之路> HAL 简介
HAL层概述 名称: HAL, Hardware Abstracting Layer,中文名字:硬件抽象层. 作用:对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节.向上衔接Andro ...
- 整理: Android HAL
这篇文章整理来自http://bbs.chinaunix.net/thread-3675980-1-1.html 在论坛中看到的Android HAL讨论,有个ID描述的比较清楚,摘录如下: temp ...
- Android照相机模块编程 照片颠倒问题及查询摄像头参数问题的解决
这两天编程弄Android照相机模块,设置好各种参数后,发现预览的时候,照片是颠倒了,不是上下颠倒而是颠倒90°. 我的手机是华为U9200,用的Android4.0.3,后来看到http://www ...
随机推荐
- Java——Spring注解
Spring常用注解使用注解来构造IoC容器用注解来向Spring容器注册Bean.需要在applicationContext.xml中注册<context:component-scan bas ...
- Centos6.4 安装fail2ban防暴力破解
Centos6.4 安装fail2ban防暴力破解 一. 安装 curl -O https://codeload.github.com/fail2ban/fail2ban/tar.gz/0.9.0 m ...
- Python 之beautifulSoup4解析库
一.节点选择器 from bs4 import BeautifulSoup if __name__ == '__main__': html = ''' <div> <ul> & ...
- select2下拉插件
下拉单选: 1.行内 1)初始化数据: <select class="form-control select5"> <option selected>张三1 ...
- CAD绘一个文字自动剧中的标注 (com接口)
主要用到函数说明: _DMxDrawX::DrawDimRotated 绘制一个线型标注.详细说明如下: 参数 说明 DOUBLE dExtLine1PointX 输入第一条界线的起始点X值 DOUB ...
- 00 python基础知识
''' ''' print('hello world!') ''' 变量 ''' # 变量的:‘tank’,会在内存中产生一份内存地址 #变量名:相当于一个门牌号,用于与变量进行绑定 # = :用来把 ...
- git学习(1)
一.git fetch 和git pull 的差别 1.git fetch 相当于是从远程获取最新到本地,不会自动merge,如下指令: git fetch orgin master //将远程仓库的 ...
- sysbench_mysql
ref http://seanlook.com/2016/03/28/mysql-sysbench/ 测试 当执行下面这个sysbench测试mysql的时候,你不知道的可能可能是: 这到底是在测试读 ...
- 腾讯云,搭建LAMP服务
lamp (Web应用软件) 编辑 Linux+Apache+Mysql/MariaDB+Perl/PHP/Python一组常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被 ...
- 曾经遇过的sql问题
曾经遇过的sql问题 问题一: 语句1: select SUM(level) from Comment 语句2: ELSE SUM(level) END as totalLevel from Comm ...