Chinaunix首页 | 论坛 | 博客
  • 博客访问: 472066
  • 博文数量: 107
  • 博客积分: 713
  • 博客等级: 上士
  • 技术积分: 1050
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-05 00:14
个人简介

呵呵

文章分类

全部博文(107)

文章存档

2015年(2)

2014年(17)

2013年(29)

2012年(52)

2011年(7)

分类: LINUX

2012-10-18 09:48:34

(有不对的地方希望大家给予指正
要了解android驱动,很重要的一点就是要熟悉HAL(硬件抽象层),HAL的作用是把Android Framework与linux内核隔离,使android不过度依赖linux kernel,从而让Android Framework开发可以在不考虑驱动程序的前提下进行(我的理解是厂商已经把驱动做在HAL层,他们没有把这一层驱动代码开源,都已经做成现成的驱动模块,我们只需要根据接口调用就可以了)。 HAL中主要有如下三个结构:
struct hw_module_t
struct hw_module_methods_t
struct hw_module_device_t
这三种结果的继承关系是:hw_module_methods_t继承struct hw_module_t,struct hw_module_t继承struct hw_module_device_t;
其中hw_module_device_t主要实现的是设备关闭的一些操作。struct hw_module_t主要实现的是设备一些基本参数,比如id,name,version等。hw_module_methods_t主要实现了设备打开等一些操控方法。我的理解是类似于linux驱动里的file_operation;
hw_get_module():能够根据模块ID寻找硬件模块动态链接库的地址,然后调用load打开动态链接库从中获取硬件模块结构体地址。
mokoid工程分析
mokoid是google提供的一个LedTest示例程序,通过了解这个工程源码,对理解android层次结构,HAL编程方法非常有意义。我们可以从网络获取这个源码。
mokid结构如下:
JNI是Java程序可以调用C/C++写的动态链接库,要通过JNI实现android的HAL层。在android下有如下两种方法访问HAL。
1、app程序直接通过service调用.so格式的JNI:这种方法比较简单,但是不规范。
2、通过manage调用service:此方法实现起来比较复杂,但是符合目前的android框架。

第一种方法:直接调用service方法的实现过程
部分代码经过修改,后面的章节会给出修改的原因。

文件:mokoid-read-only/hardware/modules/include/mokoid/led.h
        /***************************************************************************/
        struct led_module_t {
                struct hw_module_t common;
        };
        //HAL 规定不能直接使用hw_module_t结构,因此需要做这么一个继承。
        struct led_control_device_t { 
        //自定义的一个针对Led控制的结构,包含hw_device_t和支持的API操作
                struct hw_device_t common;
                /* attributes */
                int fd; //可用于具体的设备描述符
                /* supporting control APIs go here */
                int (*set_on)(struct led_control_device_t *dev, int32_t led);
                int (*set_off)(struct led_control_device_t *dev, int32_t led);
        };
        #define LED_HARDWARE_MODULE_ID "led" 
        //定义一个MODULE_ID,HAL层可以根据这个ID找到我们这个HAL stub

文件:mokoid-read-only/hardware/modules/led/led.c



总结:由此可见HAL层主要是对下面三个函数的实现。

struct hw_module_t

struct hw_module_methods_t

    struct hw_module_device_t
这三个函数包含的对设备的一些底层的控制操作。

(2)JNI层

文件:mokoid-read-only/frameworks/base/service/jni/com_mokoid_server_LedService.cpp




总结:JNI层首先根据HAL层注册的ID找到hw_module_t,

然后通过hw_module_t找到相应的led_control_t.然后JNI就可

以调用HAL里控制方法。再把这些方法进行注册。

(3)service (属于Framework层)

总结:这一步主要就是sevice加载JNI动态库,调用JNI注册的函数

(4)APP 测试程序 (属于APP层)

文件:apps/LedClient/src/com/mokoid/LedClient/LedClient.java

总结:app通过service调用

5、第二种方法:经过Manager调用service

HAL、JNI两层和第一种方法一样,所以后面只分析其他的层次。

(1)Manager (属于Framework层)

APP通过这个Manager和service通讯。

文件:mokoid-read-only /frameworks/base/core/java/mokoid/hardware/LedManager.java


ILedService.Stub就是ILedService.aidl由aidl工具自动生成的类。

因为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工程源码中已经做了这些。

(待续)
阅读(2853) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~