1、通过前面led点亮的例子,其流程如下
Android app(java)(通过loadLibrary)——>C library(C库做如下事情)——>1、JNI_Onload
2、jniRegisterNativeMethods
3、ledOpen、ledClose、ledCtrol
4、open、close、ioctl
5、Hardware driver
6、Hardware
这种应用程序通过本地接口来直接访问我们的硬件称为使用JNI接口来直接访问,如果有多个应用程序来访问,可能存在冲突。(这种方式基本上只有我们自己写的应用可以访问硬件,对于比较独特私有的硬件可以使用这种方式)。
另外一种方式是通过SystemServer硬件访问服务来统一管理,App仅将请求发送给该服务,有硬件访问服务使用Java写的,其通过JNI接口来访问硬件。
(Server指的是服务器,其提供各种硬件Service)
硬件访问服务所做的工作:
A、loadLibrary:加载C库
B、JNI_Onload:注册本地方法
分别调用各个硬件(LED/振动器/串口/屏幕等)的函数来注册本地方法
eg:register_android_server_PowerMangerService(env);等,具体的可以分析SystemServer.java
电源管理硬件的注册服务函数在com_android_server_PowerMangerService.cpp;其他的都类似
在各个硬件的注册函数里面就是调用jniRegisterNativeMethods来注册
C、SystemServer:对每个硬件使用本地方法来构造Service,然后addService
addService是SystemServer进程向service_manager进程注册,后面App应用程序进程是向service_manager进程查询获取服务,这里进程间通信是通过binder来实现通信的
D、APP应用怎么使用:获得服务(getService)、使用服务(执行Service的方法(上面注册的本地方法))
说明:这里的com_android_server_PowerMangerService.cpp就被称为JNI文件,其是用C++实现的,可以直接在里面调用open,close等系统调用来范问驱动程序,但是一般不这样做,对于复制的驱动程序,一般把open、close等系统调用写在HAL文件中,这样做如果我们修改了硬件操作,只需要编译新的so库,把其放到系统中就可以,其次硬件公司出于保密,只愿意提供HAL层的库so文件,应用层通过JNI来访问HAL库
怎么实现硬件访问服务?(举例添加led硬件服务)
A、实现JNI和HAL
com_android_server_LedService.cpp注册JNI本地方法
实现hal_led.c:里面调用open,read等系统调用访问硬件
在JNI文件中加载hal_led.c
B、修改onload.cpp调用com_android_server_LedService.cpp实现的函数
C 、实现LedService.java调用本地方法
D、修改SystemServer.java:
new LedService()
addService
E、实现ILedService.java接口给App使用