在http://blog.csdn.net/getnextwindow/article/details/47731597中,为Android系统添加了HAL模块,开发好一个硬件抽象层以后,我们通常还需要在应用程序框架中实现一个硬件访问服务。硬件访问服务通过硬件抽象层(HAL)模块来为应用程序提供读写操作。由于硬件抽象层使用c++开发,而应用程序框架中的硬件访问服务是Java语言开发的,因此,硬件访问服务必须通过JNI来调用抽象层模块的接口。
Android系统的硬件访问服务通常运行在系统进程System中,而使用这些硬件访问服务的应用程序运行在另外的进程,所以需要Binder机制实现进程通信。
接下来要开发一个硬件访问服务FregService,它实现了硬件访问服务接口IFregService。首先介绍硬件访问服务接口IFregService的定义,然后介绍硬件访问服务FregService的实现,包括它的内部实现以及调用HAL模块的JNI实现,最后介绍如何在系统进程System中启动硬件访问服务FregService。
1.硬件访问服务接口定义
Android系统使用AIDL定义跨进程访问能力的服务接口,接口文件后缀是aidl,编译系统会将AIDL文件转换成一个Java文件,然后在对他进行编译。本小节将使用AIDL定义IFregService。
在Android4.0+系统中,硬件访问服务接口定义在下面目录中:
frameworks/base/core/java/android/os/IFregService.aidl
IFregService.aidl定义如下:
1 package android.os;
2
3 interface IFregService {
4 void setVal(int val);
5 int getVal();
6 }
由于服务接口IFregService是使用AIDL语言描述的,因此,我们需要将其添加到编译脚本文件中,这样编译系统才能将其转换成Java文件,然后再对它进行编译。修改的Android.mk文件位于frameworks/base目录下面,对其中的LOCAL_SRC_FILES变量添加如下值:
services/instaboot/java/com/droidlogic/instaboot/IInstabootManager.aidl
LOCAL_SRC_FILES+= services/instaboot/java/com/droidlogic/instaboot/IInstabootManager.aidl ....
修改完编译脚本之后,我们就可以对服务接口IFregService进行编译了,命令如下:
mmm ./frameworks/base/
编译结果如下:
target Dex: framework
Copying: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.dex
target Jar: framework (out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/javalib.jar)
Install: out/target/product/MagicBox_M13/system/framework/framework.jar
我们看到最终编译出framework.jar文件,这个JAR包中就包含IFregService接口,它继承了android.os.IInterface接口。在IFregService内部定义了一个Binder本地对象Stub,实现了IFregService接口,并且继承了android.os.Binder类。此外,在IFregService.Stub类内部,还定义了一个Binder代理对象proxy,同样实现了IFregService接口。如何确定framework.jar内部是否包含IFregService接口?很简单,android的framework.jar通过反编译工具可以清楚的看到源码,反编译的具体过程在文章http://blog.csdn.net/GetNextWindow/article/details/47748493介绍了。
反编译结果如下:
2.实现硬件访问服务
FregService从IFregService.Stub类继承下来,并且实现IFregService接口的成员函数setVal和getVal。
硬件访问服务通常实现在如下目录:
base/services/java/com/android/server/FregService.java
编译方式:
mmm ./frameworks/base/service/
结果:生成的services.jar文件就包含FregService类。
3.实现硬件访问服务的JNI方法
在Android系统中,硬件访问服务的JNI方法实现在如下目录中:
frameworks/base/services/core/jni/com_android_server_FregService.cpp
完成JNI代码编写以后,我们需要修改:
frameworks/base/services/core/jni/onload.cpp
在里面增加register_android_FregService的声明和调用,onload.cpp文件实现在libandroid_servers模块中,当系统加载libandroid_servers模块的时候,就会调用onload.cpp文件中的JNI_OnLoad函数,这样就将JNI方法注册到了虚拟机当中。
最后还需要修改:
frameworks/base/services/core/jni/Android.mk
修改变量LOCAL_SRC_FILES的值,增加com_android_server_FregService.app。
编译方式:
mmm ./frameworks/base/services
结果:生成的libandroid_servers.so文件中包含了JNI方法
4:启动硬件服务
将硬件服务运行在系统进程System中,需要修改如下文件:
frameworks/base/services/java/com/android/server/SystemServe r.java
在其中添加如下代码:
try {
Slog.i(TAG, "Freg Service");
ServiceManager.addService("freg", new FregService());
} catch (Throwable e) {
Slog.e(TAG, "Failure starting Freg Service", e);
}
编译方式:
mmm ./frameworks/base/services
结果:生成了services.jar文件就包含硬件访问服务FregService,并且在系统启动时,将它运行在系统进程System中。
版权声明:本文为博主原创文章,未经博主允许不得转载。