Chinaunix首页 | 论坛 | 博客
  • 博客访问: 186806
  • 博文数量: 49
  • 博客积分: 1756
  • 博客等级: 上尉
  • 技术积分: 602
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-27 16:46
文章分类

全部博文(49)

文章存档

2014年(1)

2013年(17)

2012年(10)

2011年(5)

2010年(16)

我的朋友

分类: Android平台

2013-03-20 15:25:06

  一、硬件抽象层的图解
1、硬件抽象层在android中的位置:


在ubuntu11.04上实现android系统的硬件抽象层总结 - 大只辉 - 大只辉

 


2、Android应用程序调用下层服务:




在ubuntu11.04上实现android系统的硬件抽象层总结 - 大只辉 - 大只辉


 


3、android系统启动过程图解


在ubuntu11.04上实现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硬件抽象层会根据HELLO_HARDWARE_MODULE_ID的值在Android系统的/system/lib/hw目录中找到相应的模块,然后加载起来,并且返回hw_module_t接口给调用者使用。在jniRegisterNativeMethods函数中,第二个参数的值必须对应HelloService所在的包的路径,即com.android.server.HelloService。




五、为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的圈子中,有兴趣的可以下载来实践一下!感谢原文博主的倾情奉献!

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