主题 : 从HAL层到java应用层重写mini6410 led功能 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 70325
精华: 0
发帖: 34
金钱: 170 两
威望: 34 点
贡献值: 0 点
综合积分: 68 分
注册时间: 2012-05-18
最后登录: 2012-10-26
楼主  发表于: 2012-08-08 19:10

 从HAL层到java应用层重写mini6410 led功能

从HAL层到java应用层重写mini6410 led功能

记录了我从HAL层到应用层如何把led这个设备控制实现的过程。如果有遗漏或者错误,请各位高手指点。

led驱动的代码就不说了,以后有空再实现,
第一步,查看linux驱动设备是否工作正常。之后所有的一切,都是在这个leds设备的基础上操作完成的,所以,检查这个设备是不是有用成为了一个很重要的关键。
首先,用adb shell查看android dev下的目录,发现有leds这个设备:
ls -l /dev/leds 这个设备文件就是android中间层用来操作Linux底层led设备的。
回到android2.3.4源代码目录,在 external目录底下建立testDev目录,在下面分别建立Android.mk 和 testDev.c文件
在testDev.c这个文件里,首先写一个测试程序用来测试Leds这个文件设备能否正常运行;
testDev.c,打开设备关键是ioctl这个函数,其中,第二个参数用来控制是否打开一个led设备,第三个参数用来控制打开的是那个led。(testDev.c 和 Android.mk这2个程序可以见附件。)
全部写完之后,用./build-android编译一下,编译的时候,可以指定特定模块编译,这样比较节省时间。不能用mmm这个命令编译,这个编译了之后product的名称就不是mini6410了,这样很多库都会找不到。编译之后android的out/target/product/mini6410/system/bin/ 目录下面会生成一个叫 testDev的文件,然后将开发板开机,用adb push out/target/product/mini6410/system/bin/testDev system/bin/ 把testDev push到开发板上面去,然后用adb shell命令进入到system/bin/目录下面,运行./testDev 就可以检测leds这个设备是否运行正常。


第二步,为linux的led驱动提供android的HAL层。
HAL是android的硬件逻辑层,在这里,主要是为framework层提供一层Led的操作接口。直接操作leds设备的函数在第一步已经指明了,就是ioctl函数,但是,如何将这个功能增加到android的框架里呢?
首先,增加hardware/libhardware/modules/目录下的mydevice目录,然后在这个目录下再新建Led目录,在led目录下,分别建立led.c和Android.mk文件在mydevice这个目录下,也需要建立Android.mk文件用来搜索mydevice目录下的每个驱动设备目录。在hardware/libhardware/include/hardware 下,建立hardware目录,在下层建立mydevice/led.h,该文件用来实现一些module_id之类的宏和结构体,这里比较重要的是DEVICE_NAME一定要写对,这个就是程序需要读取的设备,还有MODULE_NAME的取名要跟Android.mk里面的LOCAL_MODULE前缀一样,否则程序加载的时候会找不到。硬件结构体是继承hw_device_t这个结构的,在这个结构体里,可以定义leds设备的fd,和这个设备需要操作的一些结构函数,比如这边就增加了set_led,用来控制Led设备的。
最后还要修改hardware/libhardware/ Android.mk,将增加好的led结构添加进去。
include $(addsuffix /Android.mk, $(addprefix $(LOCAL_PATH)/, \
            modules/gralloc \
            modules/mydevice \ --》增加这行
            tests \
        ))
        
然后编译一下,out/target/product/mini6410/system/lib/hw目录下会生成led.default.so这个文件,编译就成功了。


第三步,增加jni底层对上层的应用接口。
在这一步当中,封装了底层的.c的接口函数,使得上层Java可以调用, 做到这一步,java应用层应该也可以调用这一步生成的.so,友善提供的.so文件应该就是做到这一步生成的。
这一步当中,首先添加framework/base/services/jni目录下的com_android_server_DeviceService.cpp文件,这个文件用来动态加载jni的接口函数。为java上层提供帮助。Method_table这个表提供了底层到Java层的映射,
    static const JNINativeMethod method_table[]=
    {
        {"openLed", "()Z", (void*)led_init}, --》第一个是java层可以调用的函数名,第二个是函数签名,第三个是本层函数名
        {"set_Led", "(II)I", (void*)setLed},
    };
java层调用映射之后的字符就可以完成对底层的通讯了。全部写完之后,还要在frameworks/base/services/jni/onload.cpp这个文件当中将method_table这个表加载进系统里(JNI_OnLoad),然后在Android.mk下增加com_android_server_DeviceService.cpp文件就可以编译了。
LOCAL_SRC_FILES:= \
    com_android_server_AlarmManagerService.cpp \
    com_android_server_BatteryService.cpp \
    com_android_server_InputManager.cpp \
    com_android_server_LightsService.cpp \
    com_android_server_PowerManagerService.cpp \
    com_android_server_SystemServer.cpp \
    com_android_server_UsbService.cpp \
    com_android_server_VibratorService.cpp \
    com_android_server_location_GpsLocationProvider.cpp \
    com_android_server_DeviceService.cpp \  --》增加这行。
    onload.cpp

第四步,用aidl增加java services。
Aidl是一个工具,他可以用来增加java的services,首先,在frameworks/base/core/java/android/os/路径下增加IDeviceService.aidl接口,然后,在 frameworks/base/Android.mk里面增加这个aidl文件,编译一下,这个时候就会生成stub,新增frameworks/base/services/java/com/android/server这个路径下的DeviceService.java,这个java文件里需要继承刚才用aidl工具生成出来的IDeviceService.Stub,之后对jni接口进行再一次封装。在frameworks/base/services/java/com/android/servier/SystemServer.java里面需要增加这个服务,之后重新编译程序就可以了。

第五步,在java应用层调用底层编译好的java service服务。
用eclipse新建一个java项目,然后在这个新建的工程里面把操作的button做好,这个界面由于只是测试程序,所以就做了一个button,这个button的功能就是依次打开和关闭led灯。

本部分内容设定了隐藏,需要回复后才能看到
[ 此帖被bottles在2012-08-09 13:38重新编辑 ]
级别: 新手上路
UID: 38605
精华: 0
发帖: 27
金钱: 135 两
威望: 27 点
贡献值: 0 点
综合积分: 54 分
注册时间: 2011-02-27
最后登录: 2014-12-29
1楼  发表于: 2012-11-26 23:29
不错,支持一下!