最近在解关于Gsensor的Bug,Bug还没解掉,反而把Android的Gsensor流程走了一遍。好久不写博客了,不能偷懒啊,学了东西还是得总结一下,好让后来人不要费多少工夫,同时抛砖引玉,大家一起讨论一下,有什么错误我好纠正一下,对自己也是一种激励。言归正传,本文主要从上层的Activity一直分析到kernel的driver,路比较长,不过我喜欢搞清楚架构。

目录:

一、应用层的API;

二、Framwork中的处理;

三、C++中的JNI;

四、Kernel的Gsensor-driver;

一、应用层的API

先看一个例子,这个例子是Gsensor的最简单应用,只是用来打印x,y,z的三个值:

[java] view plain copy
  1. publicclassmainextendsActivity{
  2. privatefloatx,y,z;
  3. protectedvoidonCreate(BundlesavedInstanceState){
  4. super.onCreate(savedInstanceState);
  5. SensorManagermSensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
  6. Sensorsensor=mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
  7. SensorEventListenerlsn=newSensorEventListener(){
  8. publicvoidonSensorChanged(SensorEvente){
  9. System.out.println(e.value[0]);
  10. System.out.println(e.value[1]);
  11. System.out.println(e.value[2]);
  12. }
  13. publicvoidonAccuracyChanged(Sensors,intaccuracy){
  14. }
  15. };
  16. mSensorManager.registerListener(lsn,sensor,SensorManager.SENSOR_DELAY_GAME);
  17. }
[java] view plain copy
  1. publicclassmainextendsActivity{
  2. privatefloatx,y,z;
  3. protectedvoidonCreate(BundlesavedInstanceState){
  4. super.onCreate(savedInstanceState);
  5. SensorManagermSensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
  6. Sensorsensor=mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
  7. SensorEventListenerlsn=newSensorEventListener(){
  8. publicvoidonSensorChanged(SensorEvente){
  9. System.out.println(e.value[0]);
  10. System.out.println(e.value[1]);
  11. System.out.println(e.value[2]);
  12. }
  13. publicvoidonAccuracyChanged(Sensors,intaccuracy){
  14. }
  15. };
  16. mSensorManager.registerListener(lsn,sensor,SensorManager.SENSOR_DELAY_GAME);
  17. }

这段代码中我们重点关注这几个类:SensorManager,SensorEvent;然后我们进入到Framework中看看这两个类是如何实现,它们都做了什么操作。

二、Framework中的处理

相关文件:/frameworks/base/core/java/android/hardware/SensorManager.java;

这个SensorManager主要负责返回传感器类型,从底层获得数据。getSystemService(String name)是根据名字返回相应的Manager,这个机制也比较重要,网上有相关资料,在此不展开讨论了;mSensorManager.getDefaultSensor(type)就是获取指定类型的传感器。这些类型在API手册中都能查到,包括温度传感器,重力感应器等。registerListener注册监听器,这是为了能让ManagerSensor回调正确的接口函数,注册的时候我们可以指定sensor的灵敏度,分四个等级,API手册中有相应介绍。我们来看一下SensorManager的构造函数:

1.获取windowManager实例,监控屏幕旋转状态;

2.初始化sensorList传感器列表;调用了sensors_module_init()和sensors_module_get_next_sensor()两个本地JNI方法;

3.构造SensorThread线程(这里线程并没有开启);

系统中只维护了一个SensorManager,应用层的调用只是往SensorManager里面注册了一个监听接口,然后使能相应的Sensor,设置Sensor的参数;SensorManager的获取是通过调用getSystemService方法,这个方法会检测SensorManager是否已经存在了,如果存在了一个实例就直接返回这个实例。

下面重点分析一下SensorThread线程,这个线程的开启是在registerListener里面,SensorThread是一个死循环,他通过调用native方法sensors_data_poll方法来轮询下层发来的传感器数据。每次接受到一个数据就会调用代理listener中的onSensorChangedLocked方法,把它封装成一个消息发给自己的messagerHandler,在这里面最终调用注册的onSensorChanged方法,也就是我们上面应用程序接口的中方法。

三、C++中的JNI

相关文件:/frameworks/base/core/jni/android_hardware_SensorManager.cpp;

sensors_module_init()模块初始化-->hw_get_module()-->load(),其实就是把sensor.so的链接库加载进来;

sensor.so是与机器相关的hardware层来实现的,要在hardware下实现相应的sensor.cpp;这个文件就是跟kernel打交道的最底层的文件了。里面主要完成了打开设备文件,读取设备节点的数据。比如我们的Gsensor是走的输入输出子系统,就打开相应的event文件来读取驱动上报的坐标数据。

四、Kernel中的驱动

这个我们的实现比较简单,是走的input子系统。你可以选择用中断模式或者轮询模式来读取设备发来的数据。

五、SensorService(对比SensorManager)

其实还有一个非常重要的类没有说,就是SensorService;现在有必要把整个Sensor总结分析一下了。

系统开启之后会依次启动各种系统服务;源码在SystemServer.java中,在这里系统会new一个SensorService,SensorService中会调用JNI方法_sensors_control_init,对应com_android_server_SersorService.cpp中的android_init();这个主要是初始化SensorDevice的句柄供以后调用;下面是com_android_server_SersorService.cpp注册的JNI方法:

[java] view plain copy
  1. staticJNINativeMethodgMethods[]={
  2. {"_sensors_control_init","()I",(void*)android_init},
  3. {"_sensors_control_open","()Landroid/os/Bundle;",(void*)android_open},
  4. {"_sensors_control_close","()I",(void*)android_close},
  5. {"_sensors_control_activate","(IZ)Z",(void*)android_activate},
  6. {"_sensors_control_wake","()I",(void*)android_data_wake},
  7. {"_sensors_control_set_delay","(I)I",(void*)android_set_delay},
  8. };
[java] view plain copy
  1. staticJNINativeMethodgMethods[]={
  2. {"_sensors_control_init","()I",(void*)android_init},
  3. {"_sensors_control_open","()Landroid/os/Bundle;",(void*)android_open},
  4. {"_sensors_control_close","()I",(void*)android_close},
  5. {"_sensors_control_activate","(IZ)Z",(void*)android_activate},
  6. {"_sensors_control_wake","()I",(void*)android_data_wake},
  7. {"_sensors_control_set_delay","(I)I",(void*)android_set_delay},
  8. };

从这里我们可以看出,SensorService这个类主要是负责控制Sensor设备的。这些JNI函数最终都会调用到我们Sensor.cpp里面的实现。对比我们的SensorManager中JNI的注册:

[java] view plain copy
  1. staticJNINativeMethodgMethods[]={
  2. {"nativeClassInit","()V",(void*)nativeClassInit},
  3. {"sensors_module_init","()I",(void*)sensors_module_init},
  4. {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
  5. (void*)sensors_module_get_next_sensor},
  6. {"sensors_data_init","()I",(void*)sensors_data_init},
  7. {"sensors_data_uninit","()I",(void*)sensors_data_uninit},
  8. {"sensors_data_open","([Ljava/io/FileDescriptor;[I)I",(void*)sensors_data_open},
  9. {"sensors_data_close","()I",(void*)sensors_data_close},
  10. {"sensors_data_poll","([F[I[J)I",(void*)sensors_data_poll},
  11. };
[java] view plain copy
  1. staticJNINativeMethodgMethods[]={
  2. {"nativeClassInit","()V",(void*)nativeClassInit},
  3. {"sensors_module_init","()I",(void*)sensors_module_init},
  4. {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
  5. (void*)sensors_module_get_next_sensor},
  6. {"sensors_data_init","()I",(void*)sensors_data_init},
  7. {"sensors_data_uninit","()I",(void*)sensors_data_uninit},
  8. {"sensors_data_open","([Ljava/io/FileDescriptor;[I)I",(void*)sensors_data_open},
  9. {"sensors_data_close","()I",(void*)sensors_data_close},
  10. {"sensors_data_poll","([F[I[J)I",(void*)sensors_data_poll},
  11. };

不难看出,SensorManager主要负责的是数据的传输;

OK,到这里Sensor基本就分析完了。其中WindowManager跟Sensor打交道,实现转屏等操作,这里就先不做分析了。本人水平有限,接触android也就两个月的时间,有什么不对或者欠妥的地方欢迎指正。

更多相关文章

  1. 一款常用的 Squid 日志分析工具
  2. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  3. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  4. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  5. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  6. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  7. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  8. android中才Pull解析器生成xml文档
  9. Android(安卓)使用【AIDL】调用外部服务

随机推荐

  1. 选项卡片段
  2. android 设置壁纸几种方法
  3. android菜单参考资料
  4. android操作xml
  5. Android多媒体开发(5)————利用Android(
  6. Android内核的根文件系统
  7. Android动画一
  8. Android常见错误解析
  9. Android(安卓)常用布局
  10. Anfdroid网络编程方法