分类: Android平台
2013-03-20 15:25:06
一、硬件抽象层的图解
1、硬件抽象层在android中的位置:
2、Android应用程序调用下层服务:
3、android系统启动过程图解
二、android硬件抽象层移植:从驱动程序到应用程序
移植需要做的工作:
1、在内核空间编写硬件驱动程序,移植硬件驱动程序。
2、 编写内核驱动测试C程序,调试内核驱动。
3、在硬件抽象层中添加接口支持访问linux内核驱动程序。
4、编写JNI方法提供Java访问硬件服务接口。
5、为Android系统内置Application Frameworks层增加硬件访问服务。
6、编写java应用程序测试Application Frameworks层的硬件服务
步骤:
一、移植设备驱动程序:
1、在Android/kernel/common/driver中创建一个hello的目录
2、在Android/kernel/common/drive/hello目录中添加驱动程序hello.h,hello.c两个文件。
3、在驱动目录hello中添加两个Makefile和Kconfig文件,
其中Kconfig是在编译前执行配置命令make menuconfig时用到,而Makefile是执行编译命令make时用到的。
4、修改arch/arm/Kconfig和drivers/kconfig两个文件:在menu
"Device Drivers"和endmenu之间添加一行:source "drivers/hello/Kconfig"。这样,执行make
menuconfig时,就可以配置hello模块的编译选项了。
5、修改drivers/Makefile文件,添加一行:obj-$(CONFIG_HELLO) +=
hello/。这个是为了,在内核编译的过程中能够找到hello目录并进行编译。
6、在内核根目录配置编译选项:使用命令make
menuconfig进行驱动选择。在使用make命令进行内核编译。
二、在android系统中添加c语言编写的执行程序,测试内核驱动。测试程序一般是放在/system/bin目录下。
1、进入Android/external目录,创建一个hello的目录,作为测试程序代码目录。
2、在测试代码目录中添加驱动测试程序。Hello-test.c。
3、在测试代码目录中创建Android.mk文件并添加相应的内容,该文件为android编译标准文件,在编译程序时用到。
4、 回到Android/目录使用mmm命令编译:$mmm
./external/hello。编译成功后会在/out/target/product/gerneric/bin目录下看到可执行文件hello。其中mmm命令主要是编译单独的模块。
5、重新打包Android文件系统system.img: ~Android/$make
snod
6、运行模拟器:emulator -kernel
./kernel/common/arch/arm/boot/zImage &
7、使用adb
shell命令进入android的系统终端,进入system/bin目录,运行测试程序hello-test。
三、在硬件抽象层中增加硬件模块来和内核驱动程序交互。我们将通过设备文件/dev/hello来连接硬件抽象层模块和Linux内核驱动程序模块。
1、进入/Android/hardware/libware/include/hardware目录中添加hello.h。在hello.h中,按照Android硬件抽象层规范的要求,分别定义模块ID、模块结构体hw_module_t以及硬件接口结构体hw_device_t结构。其中hw_device_t所在的结构中定义了fd文件描述符,set_val和get_val两个方法。
2、进入Android/hardware/libhardware/modules目录,新建hello目录,并添加hello.c文件,再该目录下的hello.c文件定义了硬件抽象层的所有向上提供的接口。
3、解决上层app调用hello_device_open的权限问题。(因为/dev/hello的设备文件只有root用户可读写)具体为:进入Android/system/core/rootdir目录,修改uevent.rc文件。添加一行:/dev/hello
0666 root root。
4、继续在hello目录下新建Android.mk文件,向其中添加抽象层的内容。注意:LOCAL_MODULE的定义规则,hello后面跟有default,hello.default能够保证我们的模块总能被硬象抽象层加载到。
5、重新编译模块和打包android系统镜像system.img
:~Android$mmm hardware/libhardware/modules/hello
:~Android$make snod
重新打包后system.img中就包含我们定义的硬件抽象层模块hello.default了。这一层,我们添加了硬件抽象层的模块。现在Java应用程序还不能访问到我们的硬件。我们还必须编写JNI方法和在Android的Application
Frameworks层增加API接口,才能让上层Application访问我们的硬件。
四、为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口
1、进入:$Android/frameworks/base/services/jni目录.
2、新建com_Android_server_HelloService.cpp文件。注意文件的命令方法,com_android_server前缀表示的是包名,表示硬件服务HelloService是放在frameworks/base/services/java目录下的com/android/server目录的,即存在一个命令为com.android.server.HelloService的类。
3、修改$Android/frameworks/base/serbices/jni目录中的onload.cpp文件,在namespace
Android中添加register_android_server_Helloservice函数声明。
4、修改同目录(/frameworks/base/services/jni)下的Android.mk文件,在LOCAL_SRC_FILES变量中添加一行:
com_android_server_location_GpsLocationProvider.cpp
/
com_android_server_HelloService.cpp /
onload.cpp
5、编译和重新打包文件系统:
:~Android/$mmm frameworks/base/services/jni
:~Android/$make snod
注意,在com_Android_server_HelloService.cpp文件的hello_init()函数中,通过Android硬件抽象层提供的hw_get_module方法来加载模块ID为HELLO_HARDWARE_MODULE_ID的硬件抽象层模块,其中,HELLO_HARDWARE_MODULE_ID是在
五、为Android系统的Application Frameworks层增加硬件访问服务
注释:对于Android系统的应用程序来说,要获得硬件服务,就是在Application
Frameworks层调用相应的硬件接口服务。
1、定义应用程序与硬件服务之间的通信接口,通过代理来实现。
2、进入:~Android/frameworks/base/core/java/android/os目录。新增IHelloService.aidl接口定义文件
3、返回~Android/frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件,编译时要用到。
core/java/android/os/IVibratorService.aidl /
core/java/android/os/IHelloService.aidl/
core/java/android/service/urlrenderer/IUrlRendererService.aidl
/
4、编译IHelloService.aidl接口:~/Android$mmm
frameworks/base
:~/Android$ mmm frameworks/base
这样IHelloService.aidl生成相应的IHelloService.Stub接口。
5、
进入到frameworks/base/services/java/com/Android/server目录,新增HelloService.java文件:(HelloService主要是通过调用JNI方法init_native、setVal_native和getVal_native来提供硬件服务)。
6、修改同目录(frameworks/base/services/java/com/Android/serve)的SystemServer.java文件,在ServerThread::run函数中增加加载HelloService的代码。
7、编译HelloService和重新打包syste.img:
a) ~Android$mmm frameworks/base/services/java
b) ~Android$make snod
这样,重新打包后的system.img系统镜像文件就在Application
Frameworks层中包含了我们自定义的硬件服务HelloService了,并且会在系统启动的时候,自动加载HelloService。这时,应用程序就可以通过Java接口来访问Hello硬件服务了。
六、为Android系统内置Java应用程序测试Application
Frameworks层的硬件服务。
1、使用eclipse安装ADT后来开发应用程序,测试完后移植到android源代码当中,将Hello.java,源代码考到目录:src/shy/luo/hello/Hello.java
2、程序通过ServiceManager.getService("hello")来获得HelloService,接着通过IHelloService.Stub.asInterface函数转换为IHelloService接口。其中,服务名字“hello”是系统启动时加载HelloService时指定的,而IHelloService接口定义在android.os.IHelloService中,具体可以参考在Ubuntu上为Android系统的Application
Frameworks层增加硬件访问服务一文。这个程序提供了简单的读定自定义硬件有寄存器val的值的功能,通过IHelloService.getVal和IHelloService.setVal两个接口实现。
3、编写界面布局文件:res/layout/main.xml文件。
4、编写字符串文件res/values/strings.xml
5、编写程序描述文件AndroidManifest.xml
6、将Hello目录拷贝至packages/experimental目录,新增Android.mk文件。
7、编译和重新打包系统文件system.img
a) $mmm packages/experimental/Hello
b) $make snod
8、运行Android 模拟器。
a) emulator -kernel
kernel/common/arch/arm/boot/zImage &
b) 测试应用程序,同时检查jni的logcat文件,看看是否有权限问题。
本文属于原创作品,欢迎转载:http://linhui.568.blog.163.com/blog/static/96265268201172083630288/
关于该几篇android硬件抽象层的虚拟机(13G)和android源代码的整个文件包(6.6G)我正在上传到115的圈子中,有兴趣的可以下载来实践一下!感谢原文博主的倾情奉献!