Welcome 微信登录

首页 / 操作系统 / 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-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工程中实现了上述两种方法。下面将详细介绍这两种方法的实现原理。