华清远见讲师 刘洪涛
一、概述
本文希望通过分析台湾的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等。
目前存在两种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-only
3、结构分析
|-- 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工程中实现了上述两种方法。下面将详细介绍这两种方法的实现原理。
4、第一种方法:直接调用service方法的实现过程
下面分析第一种方法中,各层的关键代码。
(1)HAL层
一般来说HAL moudle需要涉及的是三个关键结构体:
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
下面结合代码说明这3个结构的用法。部分代码经过修改,后面的章节会给出修改的原因。
文件:mokoid-read-only/hardware/modules/include/mokoid/led.h
文件:mokoid-read-only/hardware/modules/led/led.c
(2)JNI层
文件:mokoid-read-only/frameworks/base/service/jni/com_mokoid_server_LedService.cpp
(3)service (属于Framework层)
文件:frameworks/base/service/java/com/mokoid/server/LedService.java
(4)APP 测试程序 (属于APP层)
文件:apps/LedClient/src/com/mokoid/LedClient/LedClient.java
5、第二种方法:经过Manager调用service
HAL、JNI两层和第一种方法一样,所以后面只分析其他的层次。
(1)Manager (属于Framework层)
APP通过这个Manager和service通讯。
文件:mokoid-read-only /frameworks/base/core/java/mokoid/hardware/LedManager.java
因为LedService和LedManager在不同的进程,所以要考虑到进程通讯的问题。Manager通过增加一个aidl文件来描述通讯接口。
文件:mokoid-read-only/frameworks/base/core/java/mokoid/hardware/ILedService.aidl
(2)SystemServer (属于APP层)
文件:mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedSystemServer.java
(3)APP 测试程序(属于APP层)
文件:mokoid-read-only/apps/LedTest/src/com/mokoid/LedTest/LedTest.java
五、实验中需要注意的问题
将下载后的源码放到你的android源码目录下,然后编译系统。本实验用的android版本为2.1。实验的过程中大致出现过以下几个问题:
1、目标系统中没有生成LedClient.apk或LedTest.apk应用程序
编译完成后,没有在目标系统的system/app/目录下找到LedClient.apk或LedTest应用程序。只有通过单独编译LedClient或LedTest才能在目标目录中生成。方法如下:
#mmm mokoid-read-only/apps/LedTest/
检查原因后发现mokoid-read-only/apps/LedTest/Android.mk
LOCAL_MODULES_TAGS :=user
而我们的s5pc100系统在配置时tapas时选择的是eng,所以没有装载到目标系统
所以修改LedTest和LedClient的Android.mk
LOCAL_MODULES_TAGS :=user eng
再次编译即可自动装载到目标系统/system/app/目录下。
2、启动后没有图标,找不到应用程序
目标系统启动后找不到两个应用程序的图标。仔细阅读logcat输出的信息发现:
E/PackageManager( 2717): Package com.mokoid.LedClient requires unavailable shared library com.mokoid.server; failing!
原因是找不到 com.mokoid.server。检查mokoid-read-only/frameworks/base/Android.mk发现系统将LedManager和LedService编译成 mokoid.jar库文件。为了让应用程序可以访问到这个库,需要通过com.mokoid.server.xml 来设定其对应关系。解决方法:拷贝com.mokoid.server.xml到目标系统的system/etc/permissions/目录下
此时两个应用的程序的图标都正常出现了。
3、提示找不到 JNI_OnLoad
按照以前的实验加入下列代码:
4、需要针对你的目标平台修改HAL的Makefile
修改mokoid-read-only/hardware/modules/led/Android.mk
LOCAL_MODULE := led.default
5、在eclipse中编译不了LedSystemServer.java
原因是程序中要用到ServiceManager.addService,这需要系统权限。
解决方法可以把应用程序放入Android源码中编译,并确保以下两点:
(1)在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性。
(2)修改Android 加入LOCAL_CERTIFICATE := platform.
当然:mokoid工程源码中已经做了这些。
(2)经过Manager调用service
分享到:
相关推荐
Android HAL 实例解析 Android HAL(Hardware Abstraction Layer)是一种硬件抽象层,旨在保护硬件提供商的知识产权,避免 Linux 的 GPL 限制。HAL 的主要目的是将 Android 框架与 Linux 内核隔开,让 Android 框架...
在“day0220100329”这个文件名中,我们可以推测这是课程的第二天内容,可能涵盖了更深入的HAL开发实践或者特定模块的实例分析。可能包括了如何处理中断、线程同步、错误处理等方面的知识。 此外,2010年3月的培训...
实例解析AndroidHAL的开发方法-华清远见.pdf
### Android HAL 层详细介绍 #### 一、HAL层概述 Android HAL(硬件抽象层)是Android系统中的一个重要组成部分,它的引入主要是为了满足不同硬件制造商的需求,即能够在一定程度上保护各自的硬件驱动程序源代码不...
3. **创建HAL实例**:系统调用HAL库中的函数来创建HAL实例,这个实例包含了硬件模块接口(`hw_module_t`)和硬件设备接口(`hw_device_t`)。 4. **执行硬件操作**:通过HAL实例提供的接口,应用程序或服务可以对...
### Android HAL 分析报告 #### 一、HAL 简介 Android HAL(Hardware Abstract Layer,硬件抽象层)是Google为了满足部分硬件厂商对于源码保密的需求而提出的一个概念。HAL 的目标在于创建一个隔离层,它使得...
Android HAL实例解析 Android Linux kernel 编译环境.doc Android 底层开发.pdf Android+Porting+Guide+v1.pdf Android根文件系统分析总结.pdf Android入门之HelloWorld.pdf Android系统开发--HAL层开发基础(1).doc ...
10. **实例分析**:通过具体的案例分析,如相机驱动或蓝牙驱动的开发,让读者了解实际开发过程中的问题和解决方案。 这本书全面涵盖了Android系统中硬件层面的开发技术,对于想要深入理解Android系统并从事相关开发...
- **HAL Stub的分析与设计**:采用面向对象的分析与设计方法来开发HAL Stub。 #### 2.2 HAL Stub Class - **HAL Stub类**:定义HAL Stub类,实现HAL接口。 #### 2.3 HAL Stub Interface - **HAL Stub接口**:...
1:Android通过JNI调用驱动程序(完全解析实例) 2:Android驱动开发入门及手机案例开发分析.pdf 3:android_hal.pdf 4:Android通过JNI调用驱动程序(完全解析实例)
- **框架和服务**:负责管理HAL实例和服务的注册与查找。 - **HAL库**:包含了具体的硬件接口实现。 - **硬件模块接口**:定义了硬件模块应遵循的行为规范。 #### 提供的文件分析 从给定的文件列表来看,这些文件...
**Android LED HAL (硬件抽象层)详解** 在Android操作系统中,LED驱动是设备硬件...这个过程涵盖了HAL接口设计、Linux驱动开发、Android系统集成以及功耗管理等多个方面,是理解Android系统与硬件交互的一个典型实例。
在Android环境下,这些通常由硬件抽象层(HAL)处理,开发者一般不需要直接操作,但了解这些原理有助于更好地理解和优化设备性能。 在实际编程中,Android提供了多种工具来监控和管理内存,如Android Profiler,它...
《Android深度探索 卷1:HAL与驱动开发》是一本专为Android系统开发者和爱好者编写的书籍,旨在深入解析Android系统的硬件抽象层(HAL)以及驱动程序开发的关键技术和实践。这本书全面涵盖了Android系统中硬件接口的...
"Android源代码情景分析的实例代码"提供了这样的机会,让我们能够通过罗升阳先生的配套解析,更直观地理解和学习Android系统的内部运作机制。这份资源包含了一系列与Android源代码相关的实例代码,旨在帮助开发者...
在Android系统中,电源管理是一项至关重要的功能,它关乎设备的能耗、电池寿命以及用户体验。本文将深入探讨如何通过Power事件来实现设备的休眠和唤醒机制,这在某些特定的应用场景,如远程控制、定时任务等,尤其...