一:JNI接口访问硬件
Android应用程序通过加载C库,来访问硬件驱动程序来操作硬件设备。
技术要点是:
1:Android应用程序通过loadLibrary来加载C Library
2:在C Library里面实现JNI_Onload,目的的一旦C库被加载这个JNI_Onload方法就会被调用。
3:在JNI_Onload方法里面注册相关的本地方法,注册本地方法即:使得C语言实现的函数可直接被Java语言调用;在C语言实现的函数里调用Linux 系统 标准的C 接口 如:open、read等来真正的服务设备驱动程序,进而操作硬件。
如果开发的硬件比较独特,只有自己开发的应用程序可访问,可使用以上这个方法来实现Android 应用程序对硬件的访问。
二:硬件访问服务
如果硬件设备同时被多个应用程序来访问,如果每个应用程序都通过JNI方式来访问这个硬件设备;那么就有可能导致冲突。例如屏幕:如果ABC三个应用程序都同时来写屏幕,那么屏幕就会被划得乱七八糟的;又比如ABC三个应用程序都来操作声卡,那么播放出来的声音就很嘈杂。面对这种情况,该怎么办?同一时刻只让一个应用程序来访问硬件设备,那么这个应用程序就称为SystemServer ,把应用程序对硬件访问的请求发给SystemServer ,并由SystemServer 来统一管理。
要点:systemserver可以访问硬件,而SystemServer 是使用Java语言来实现的,而访问硬件使用的是C语言,因此,在中间得进过JNI接口。
1:SystemServer 通过 loadLibrary来加载C库
2:在JNI_Onload里注册本地方法
在Android系统里面有很多的硬件,声卡,屏幕,按键,led,串口等,每一个硬件的本地操作函数都不一样,这就需要在JNI_Onload里调用各个硬件的相关函数来注册本地方法。
3:SystemServer
①:对每一个硬件使用本地方法构造服务
②:把服务添加到系统里的ServiceManager里去,这些服务才能应用程序所使用,ServiceManager进程管理做系统里的所有服务。
4:app使用服务,向ServiceManager查询获得服务
①:通过getService来获得服务
②:通过服务的本分来使用服务
怎么样实现硬件访问服务
1:实现JNI和HAL
①:在com_android_server_xxx.cpp里面注册JNI本地方法。并加载HAL文件
②:提供open、write、ioctl等接口
2:修改oload.cpp
调用com_android_server_xxx.cpp提供的注册方法
3:实现服务xxxx.java 调用本地方法
4:修改SystemServer.java
①:创建对应的服务实例化对象 new xxxxx();
②:吧实例化出来的对象添加到系统里 addServer
5:实现Ixxxx.java 接口 供应用程序使用
三:源码流程
在SystemServer进程中执行main方法
public static void main(String[] args) {
new SystemServer().run();
}
在main方法中执行SystemServer的run方法。
在run方法中加载C库
private void run(){
……
// Initialize native services.
System.loadLibrary("android_servers");
nativeInit();
……
// Start services. 启动其他服务,startOtherServices中定义各种服务的实例化对象,
//并添加进系统
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
}
private void startOtherServices() {
……
IAlarmManager alarm = null;
MountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
……
//创建服务的实例化对象
Slog.i(TAG, "Vibrator Service");
vibrator = new VibratorService(context);
//往系统里面添加这个服务
ServiceManager.addService("vibrator", vibrator);
Slog.i(TAG, "Consumer IR Service");
consumerIr = new ConsumerIrService(context);
ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
}
以VibratorService服务为例:在这个服务里面声明一些本地方法,并调用这些本地方法
定义在frameworks/base/services/core/java/com/android/server/VibratorService.java
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
……
……
native static boolean vibratorExists();
native static void vibratorOn(long milliseconds);
native static void vibratorOff();
……
……
}
整个过程涉及到3个进程
在SystemServer进程中向SystemManager(SystemManager进程管理着系统里面所有的访问)进程注册和添加service,之后应用程序可向SystemManager查询和获取某个服务,最后把这个请求发送给SystemServer。