首页 / 操作系统 / Linux / Android HAL实例解析
一、概述
本文希望通过分析台湾的Jollen的mokoid 工程代码,和在s5pc100平台上实现过程种遇到的问题,解析Andorid HAL的开发方法。 二、HAL介绍
现有HAL架构由Patrick Brady (Google) 在2008 Google I/O演讲中提出的,如下图。 Android的HAL是为了保护一些硬件提供商的知识产权而提出的,是为了避开linux的GPL束缚。思路是把控制硬件的动作都放到了Android HAL中,而linux driver仅仅完成一些简单的数据交互作用,甚至把硬件寄存器空间直接映射到user space。而Android是基于Aparch的license,因此硬件厂商可以只提供二进制代码,所以说Android只是一个开放的平台,并不是一个开源的平台。也许也正是因为Android不遵从GPL,所以Greg Kroah-Hartman才在2.6.33内核将Andorid驱动从linux中删除。GPL和硬件厂商目前还是有着无法弥合的裂痕。Android想要把这个问题处理好也是不容易的。 总结下来,Android HAL存在的原因主要有: 1. 并不是所有的硬件设备都有标准的linux kernel的接口 2. KERNEL DRIVER涉及到GPL的版权。某些设备制造商并不原因公开硬件驱动,所以才去用HAL方 式绕过GPL。 3. 针对某些硬件,An有一些特殊的需求 三、HAL内容
1、HAL 主要的储存于以下目录:
(注意:HAL在其它目录下也可以正常编译)l libhardware_legacy/ - 旧的架构、采取链接库模块的观念进行l libhardware/ - 新架构、调整为 HAL stub 的观念l ril/ - Radio Interface Layer l msm7k QUAL平台相关 主要包含以下一些模块:Gps、Vibrator、Wifi、Copybit、Audio、Camera、Lights、Ril、Overlay等。2、两种 HAL 架构比较 目前存在两种HAL架构,位于libhardware_legacy目录下的“旧HAL架构”和位于libhardware目录下的“新HAL架构”。两种框架如下图所示。 图3.1 旧HAL架构 图3.2 新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编程方法。 四、mokoid 工程代码下载与结构分析
1、mokid项目概述
modkoid工程提供了一个LedTest示例程序,是台湾的Jollen用于培训的。对于理解android层次结构、Hal编程方法都非常有意义。2、下载方法
#svn checkout http://mokoid.googlecode.com/svn/trunk/mokoid-read-only3、结构分析
|-- Android.mk |-- apps //两种应用测试方法| |-- Android.mk| |-- LedClient //直接调用service来调用jni| | |-- AndroidManifest.xml| | |-- Android.mk| | `-- src| | `-- com| | `-- mokoid| | `-- LedClient| | `-- LedClient.java //第1种方式应用程序实现代码| `-- LedTest //通过manager来调用jni| |-- AndroidManifest.xml| |-- Android.mk| `-- src| `-- com| `-- mokoid| `-- LedTest| |-- LedSystemServer.java //开启了一个后台service,下文会有解释| `-- LedTest.java //第2种方式应用程序实现代码|-- dma6410xp //这个目录可以不要| |-- AndroidBoard.mk| |-- AndroidProducts.mk| |-- BoardConfig.mk| |-- dma6410xp.mk| |-- init.dma6410xp.rc| |-- init.goldfish.sh| `-- init.rc|-- frameworks //框架代码| |-- Android.mk| `-- base| |-- Android.mk| |-- core| | `-- java| | `-- mokoid| | `-- hardware| | |-- ILedService.aidl| | `-- LedManager.java //实现了Manager,给第2种方法用| `-- service | |-- Android.mk| |-- com.mokoid.server.xml| |-- java| | `-- com| | `-- mokoid| | `-- server| | `-- LedService.java //Framework service代码| `-- jni| |-- Android.mk| `-- com_mokoid_server_LedService.cpp //jni代码|-- hardware| |-- Android.mk| |-- libled| | |-- Android.mk| | `-- libled.c| `-- modules| |-- Android.mk| |-- include| | `-- mokoid| | `-- led.h| `-- led| |-- Android.mk| `-- led.c //led stub 硬件控制代码`-- README.txt Android的HAL的实现需要通过JNI(Java Native Interface),JNI简单来说就是java程序可以调用C/C++写的动态链接库,这样的话,HAL可以使用C/C++语言编写,效率更高。在Android下访问HAL大致有以下两种方式: (1)Android的app可以直接通过service调用.so格式的jni (2)经过Manager调用service 上面两种方法应该说是各有优缺点,第一种方法简单高效,但不正规。第二种方法实现起来比较复杂,但更符合目前的Android框架。第二种方法中,LegManager和LedService(java)在两个进程中,需要通过进程通讯的方式来通讯。 mokoid工程中实现了上述两种方法。下面将详细介绍这两种方法的实现原理。