传感器SensorService详细分析.docx
- 文档编号:25761919
- 上传时间:2023-06-13
- 格式:DOCX
- 页数:22
- 大小:1.04MB
传感器SensorService详细分析.docx
《传感器SensorService详细分析.docx》由会员分享,可在线阅读,更多相关《传感器SensorService详细分析.docx(22页珍藏版)》请在冰豆网上搜索。
传感器SensorService详细分析
SensorService相关架构和流程指导
1.整体架构
Applications层是使用传感器实现各种功能的具体应用程序,用来接收Sensor返回的数据,并处理实现对应的UI效果和特定功能,比如翻转静音、体感通话等功能。
Framework层为应用层提供register、unRegister等接口,同时通过JNI建立与Native层的联系,主要代码有SensorManager.java和SystemSensorManager.java。
另外,自动转屏、自动调节亮度、距离传感器控制亮屏和灭屏等功能也是在framework层实现。
如果想用现有传感器通过算法合成其他传感器功能,也可以在本层添加,但由于不是Android原有接口,外部第三方APK无法使用。
主要代码路径为:
framework/base/core/java/android/hardware/
framework/base/core/jni/android_hardware_SensorManager.cpp
Libraries表示动态库,它封装了整个Sensor的IPC机制,如SensorManager是客户端,SensorService是服务端,而HAL部分是封装了服务端对Kernel的直接访问。
主要代码路径为:
framework/native/libs/gui(生成libgui.so)
framework/native/services/sensorservice(生成libsensorservice.so)
hardware/qcom/sensors或hardware/hisense/sensors(生成sensor.xxx.so)
驱动注册到Kernel的InputSubsystem上,然后通过EventDevice把Sensor数据传到HAL层,准确说是HAL从Event读。
硬件挂在I2C总线上。
2.类图
Sensor框架分为三个层次,客户度、服务端、HAL层,服务端负责从HAL读取数据,并将数据写到管道中,客户端通过管道读取服务端数据。
客户端主要类
SensorManager.java:
从android4.1开始,SensorManager被定义为一个抽象类,定义了一些主要的方法,该类是应用层直接使用的类,提供给应用层的接口。
SystemSensorManager.java:
继承于SensorManager.java类,是客户端消息处理的实体,应用程序调用getSystemService(Context.SENSOR_SERVICE)方法获取SensorService时,实际上获取的就是SystemSensorManager的实例。
SensorEventListener接口:
用于注册监听的接口,应用层必须实现该接口,并重写接口的两个方法,实现对获取到的Sensor数据的处理。
android_hardware_SensorManager.cpp:
提供在Java层和Native层之间通信的JNI接口。
Receiver:
android_hardware_SensorManager.cpp的内部类,保存了一个指向SensorEventQueue的指针,利用消息队列监听服务端事件上报,可以将消息队列中获取的数据回调到Java层。
SensorManager.cpp:
sensor在Native层的客户端,负责与服务端SensorService.cpp通信
SenorEventQueue.cpp:
消息队列,保存了指向SensorEventConnection对象的指针,实现与SensorService之间的命令传输和数据读取。
服务端主要类
SensorService.cpp:
服务端数据处理中心
SensorEventConnection:
SensorService.cpp的内部类,从BnSensorEventConnection继承来,实现接口ISensorEventConnection的一些方法,ISensorEventConnection在SensorEventQueue会保存一个指针,指向调用服务接口创建的SensorEventConnection对象
BitTube.cpp:
在这个类中创建了管道,用于服务端与客户端读写数据
SensorDevice:
负责与HAL进行通信,传递命令和数据。
HAL层
Sensor.h是google为Sensor定义的Hal接口,单独提出去
3.API调用流程
当界面onResume()或者APP需要接收传感器数据的时候,应用层通过如下调用流程enable传感器,并指定接收到数据后的处理。
其中mSensorEventListener是实现SensorEventListener接口的子类对象,在该子类中必须重写onSensorChange()和onAccuracyChanged(),对驱动上报的传感器数据进行处理。
这两个方法的实现可以为空,表示对收到的数据不做任何处理。
当界面切到后台或不再需要接收传感器数据时,通过调用以下方法停止接收数据,并尝试将该Sensor关闭。
4.SensorService启动
应用层通过getSystemService()获取注册到ServiceManager中的系统服务,SENSOR_SERVICE返回的是SystemSensorManager类的对象,该类最终会通过Binder方式连接到Native层的SensorService。
SensorService.cpp的继承关系如上图所示,它的直接父类是BnSensorServer,BinderService和Thread,SensorManager.cpp通过Binder机制与SensorService.cpp进行通信。
SensorService的启动调用流程如下。
instantiate()方法是SensorService从BinderService类中继承的,具体实现如下图所示,该方法实际上就是生成了一个SensorService对象,并将其添加到ServiceManager中。
从addService的函数声明可以看出,第二个参数是对newSensorService()对象的强引用,因此当第一次构建sp强引用计数时,会调用SensorService:
:
onFirstRef()函数。
onFirstRef()函数主要完成以下工作:
初始化SensorDevice;获取HAL层传感器列表,根据支持的HardwareSensor,初始化VirtualSensor列表,最终形成可支持的完整传感器列表;调用run()函数启动线程。
SensorDevice是一个单实例类,当调用getInstance()时,创建对象的工作由其父类Singleton
SensorDevice的构造函数中首先加载HAL的库文件,并创建SensorModule的对象。
加载库文件时会依次获取"ro.hardware.sensors","ro.hardware","ro.product.board","ro.board.platform","ro.arch"对应的属性值,然后分别在vendor/lib/hw和system/lib/hw下查找名为sensors.xxx.so的库文件(xxx为属性值),如果这些文件都找不到,则查找sensors.default.so。
按此顺序最先找到的库文件会最终被加载。
如果加载成功会调用sensors_open_1()函数去打开传感器设备,该函数的最终实现是在multihal.cpp或者sensors.cpp的open_sensors()中。
接着通过get_sensors_list函数获取NativeSensorManager中的传感器列表,并依次将列表中的传感器置为非活跃状态。
SensorDevice的初始化工作完成后,SensorService的构造函数会获取HAL层的传感器列表,并将列表中的传感器逐个进行注册。
其中mSensorList用于保存SensorService中支持的全部传感器列表,mSensorMap中保存SensorHandle与Sensor对象指针的映射,mLastEventSeen保存SensorHandle与SensorEvent的映射,每接收到一次传感器事件,就会将对应的event更新一次。
注册完从HAL层获取的传感器列表后,根据是否支持陀螺仪,将旋转矢量、重力、线性加速度、方向传感器注册到VirtualSensor。
除了会将这些虚拟传感器类型添加到上面的三个集合外,还需要添加到mVirtualSensorList中。
最终,mSensorList中就保存了包含HardwareSensor和VirtualSensor在内的,系统所能支持的全部传感器类型,
onFirstRef()函数最后调用run()函数来启动threadLooper()。
threadLooper函数的核心功能就是不断循环等待获取HAL层传过来的传感器事件,对事件进行处理后分发给客户端。
循环体中首先通过device.poll()方法等待HAL层数据,数据到来后读取到mSensorEventBuffer中。
该方法的最终实现在sensor_poll_context_t:
:
pollEvents()方法中。
然后对当前所有的ActiveConnections做一个备份,并保存到有序Vector中。
这样做是因为在本次循环尚未执行完时,有可能其中的一些Connection就已经被移除了,特别是One-Shot类型的事件。
接下来,如果poll到的事件中存在wake-upSensorEvent,则申请一个PARTIAL_WAKE_LOCK类型的锁,阻止CPU进入休眠。
然后用mSensorEventBuffer中最新的事件更新registerSensor()时初始化的mLastEventSeen,每个handle都只保留最新的一个事件。
如果有虚拟传感器被启用,则会将Buffer中的传感器事件先传到SensorFusion中做一些处理,然后调用具体的虚拟传感器融合生成一个新的事件添加到Buffer中。
如果事件生成成功,则重新更新mLastEventSeen中对应虚拟传感器的最后一次event。
最后,通过SensorEventConnection:
:
sendEvents()方法将Buffer中的传感器事件传输到客户端。
sendEvents函数会过滤出只属于该Connection的事件进行上报,具体处理在传感器事件获取一节再详细讨论。
至此,SensorService的启动完成。
当应用层调用getSystemService()获取传感器服务时,就能够连接到Native层的SensorService,对传感器进行控制。
5.getDefaultSensor
1
TYPE_ACCELEROMETER
14
TYPE_MAGNETIC_FIELD_UNCALIBRATED
2
TYPE_MAGNETIC_FIELD
15
TYPE_GAME_ROTATION_VECTOR
3
TYPE_ORIENTATION
16
TYPE_GYROSCOPE_UNCALIBRATED
4
TYPE_GYROSCOPE
17
TYPE_SIGNIFICANT_MOTION
5
TYPE_LIGHT
18
TYPE_STEP_DETECTOR
6
TYPE_PRESSURE
19
TYPE_STEP_COUNTER
7
TYPE_TEMPERATURE
20
TYPE_GEOMAGNETIC_ROTATION_VECTOR
8
TYPE_PROXIMITY
21
TYPE_HEART_RATE
9
TYPE_GRAVITY
22
TYPE_TILT_DETECTOR
10
TYPE_LINEAR_ACCELERATION
23
TYPE_WAKE_GESTURE
11
TYPE_ROTATION_VECTOR
24
TYPE_GLANCE_GESTURE
12
TYPE_RELATIVE_HUMIDITY
25
TYPE_PICK_UP_GESTURE
13
TYPE_AMBIENT_TEMPERATURE
TYPE_MOTION_ACCL
Framework层一共定义了26种传感器的整型常量,其中21至25是AndroidL新增的支持类型。
应用层可以通过引用这些字符串获得对应的传感器对象。
如果想获得这26种之外的传感器对象,可以通过在getDefaultSensor方法中直接传入该Sensor对应的type数值获取,但这种方法不便于应用层使用。
最佳方案是在Sensor.java中添加整型常量,应用层只需要引用相应的常量名,而不需要关心具体的type数值。
但Sensor.java必须确保定义的常量与所代表的传感器type值相对应,不能随便赋值。
getDefaultSensor方法用于获取指定类型的传感器对象。
如果存在多个相同类型的传感器,只返回列表中满足条件的第一个。
getDefaultSensor(int)方法在5.0之前就一直存在,但AndroidL上对该方法的实现进行了修改,增加了对wakeUpSensor类型的处理。
TYPE_PROXIMITY、TYPE_SIGNIFICANT_MOTION、TYPE_TILT_DETECTOR、TYPE_WAKE_GESTURE、TYPE_GLANCE_GESTURE、TYPE_PICK_UP_GESTURE这六种类型应默认为wake-upSensor。
如果驱动侧没有为这六种传感器添加wake-up标识(SENSOR_FLAG_WAKE_UP_SENSOR),或者为其他传感器添加了wake-up标识,通过getDefaultSensor(int)方法都无法返回该传感器对象。
getDefaultSensor(int,boolean)是5.0上新增的方法,可用于获取指定type和wakeUp标识的传感器对象。
比如8952上同时存在两种TYPE_PROXIMITY类型传感器,一个是可唤醒,一个不可唤醒。
如果用getDefaultSensor(int)只能获取可唤醒的。
但使用getDefaultSensor(int,false)就可以获取到非唤醒类型的距离传感器对象。
由于AndroidL之前的平台都只有getDefaultSensor(int)接口,为兼容以前的项目,应用层基本都是使用该方法获取指定类型传感器对象。
为保证应用层能够正确获取到传感器对象,驱动在配置wakeUpSensor标识时应按照该方法指定的六种传感器实施。
6.registerSensorListener
Register执行时主要有两大步骤:
一是创建framework与SensorService之间的数据通道,通过newSensorEventQueue()实现;二是将对应类型的传感器使能,通过addSensor()实现。
对于应用层而言,调用的API接口是SensorManager中的registerListener()方法,但SensorManager是一个abstractClass,主要负责将API接口提供给应用层调用,SystemSensorManager是其子类,该类中提供了方法的具体实现。
mSensorListeners是一个HashMap,保存了SensorEventListener对象与SensorEventQueue对象的对应关系。
Register开始执行时首先从mSensorListeners中检查该listener是否之前已经注册过,如果已经注册过直接调用addSensor启用Sensor,否则先创建一个SensorEventQueue对象,建立framework到Native的数据传输管道,然后再启用传感器。
因为同一个SensorEventListener对象中有可能会处理多种类型传感器的数据,所以同一个listener有可能会同多个Sensor进行绑定。
Registerlistener时如果发现mSensorListener表中已经存在该listener对象,则直接调用addSensor方法检查listener本次绑定的Sensor是否已启用,如果已启用则结束本次操作,否则继续启用本次要绑定的Sensor,但不会创建新的数据管道。
也就是说同一个listener可以被绑定到多种传感器上,但不可以被绑定到同一种类型的传感器上两次;一个Listener只能对应一个数据通道。
SensorEventQueue是BaseEventQueue的子类,在SensorEventQueue的构造函数中会首先构造BaseEventQueue,通过JNI调用将该BaseEventQueue对象与Native层进行关联,同时SensorEventQueue对象中也会保存一个对listener对象的引用。
nativeInitSensorEventQueue:
该方法首先调用SensorManager.cpp中的createEventQueue()创建同SensorService之间的数据传输通道。
mSensorServer是对ISensorServer对象的强引用,在SensorManager初始化时通过getService()方法在ServiceManager中查找“sensorservice”对应的服务,并赋值给mSensorServer。
由第4小节可知,ServiceManager中返回的就是SensorService实例。
从SensorService的类图也能看出,SensorService是ISensorServer的子类。
CreateSensorEventConnection()方法创建了一个SensorEventConnection对象,并将该对象的强引用返回给SensorManager。
SensorEventConnection是SensorService的内部类,该类在构造时主要进行了一些初始化参数列表工作,其中最主要的操作是newBitTube(),创建完成后,SensorEventConnection中会保存一个对BitTube对象的强引用。
BitTube是一个字节管道,可以在进程间进行数据传递。
在构造BiTube对象时,首先创建一对匿名的、互相连接的Unix域套接字,然后将用于数据接收的Socket赋给mReciveFd,将用于数据发送的Socket赋给mSensorFd。
现在SensorService中的这部分工作已经完成,mSensorEventConnection中保存了对BitTube对象的强引用,SensorManager保存了对mSensorEventConnection的强引用。
接着SensorManager将mSensorEventConnection作为参数构造SensorEventQueue对象。
SensorEventQueue的构造函数中主要工作是初始化mRecBuffer数组,其中ASensorEvent结构体定义与hardware/sensors.h中sensors_event_t结构体完全一致。
由于SensorManager中生成的是SensorEventQueue的强引用,onFirstRef()函数会被调用。
该函数的执行结果就是得到了mSensorEventConnection中保存的mBitTube对象引用。
由此,createSensorEventQueue()函数执行完成后,mSensorEventConnection中保存了mBitTube的引用,mSensorEventQueue中保存了mSensorEventConnection和mBitTube的引用。
再返回到JNI部分,现在nativeInitSensorEventQueue中获得了mSensorEventQueue对象的引用,然后通过调用android_os_MessageQueue_getMessageQueue()得到一个MessageQueue对象的引用,利用mSensorEventQueue和mMessageQueue,以及Java层SensorEventQueue对象来构造Receiver类实例。
Receiver负责监听服务端事件,并将事件回调给Java层SensorEventQueue进行分发。
事件监听的文件描述符及回调接口在onFirstRef函数中指定。
mSensorQueue->getFd()中返回的是mBitTube中的mReceiveFd,this指定了监听到事件时的回调对象,当消息队列监听到mReceiveFd中有事件产生时,就会回调this->handleEvent()方法对事件进行处理。
handleEvent函数会对数据进行分类,最后回调Java层SensorEventQueue中的dispatchSensorEvent方法把数据分发到对应的SensorEventListener对象进行处理。
至此,第一步newSensorEventQueue()完成。
第二步调用addSensor()方法启用传感器。
首先从mActiveSensors中检查该传感器是否已激活,如果已激活则返回false。
但是,mActiveSensors是BaseEventQueue的成员变量,不是SystemSensorManager的全局变量,每一个BaseEventQueue对象都对应一个mActiveSensors。
考虑到一个BaseEventQueue只能对应一个SensorEventListener,所以除非是mListener和Sensor对象都相同才会返回false,否则不管是同一种传感器注册了另一个Listener对象,还是同一个Listener注册到另一种传感器上,都会继续执行enableSensor。
enableSensor()会调用JNI层的nativeEnableSensor()函数,然后依次调用SensorEventQueue—>SensorEventConnection中的enableDisable()函数,由于注册Listener时是启用传感器,所以会执行SensorService的enable()函数,同时SensorEventConnection会将自身作为参数传递给enable()函数。
enable()函数会首先检查要启用的传感器是否已处于激活状态,如果未激活,则创建SensorRecord对象,用于管理连接到该类型传感器的SensorEventConnection对象。
创建完成后将SensorEventConnection对象保存到其中,同时将该传感器handle和SensorRecord对象添加到mActiveSensors中。
如果已激活,则只将mConnection添加到SensorRecord中,如果该传感器数据上报类型为ON_CHANGE,则立即将上一次得到的数据通过新mConnection上报。
Sensor激活状态检查完成后,将要启用的SensorHandle保存到mConnection中,用于标识该通道可以传递哪些类型传感器的数据,然后将该mConnection添加到mActivieConnection中。
最后调用activate方法激
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 传感器 SensorService 详细 分析