已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
传感器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/q/sensors或hardware/hisense/sensors(生成sensor.xxx.so)驱动注册到Kernel的Input Subsystem上,然后通过Event Device把Sensor数据传到HAL层,准确说是HAL从Event读。 硬件挂在I2C总线上。 2.类图SensorClassDiagram.jpg Sensor框架分为三个层次,客户度、服务端、HAL层,服务端负责从HAL读取数据,并将数据写到管道中,客户端通过管道读取服务端数据。 客户端主要类SensorManager.java从android4.1开始,SensorManager被定义为一个抽象类,定义了一些主要的方法,该类是应用层直接使用的类,提供给应用层的接口。 SystemSensorManager.java继承于SensorManager.java类,是客户端消息处理的实体,应用程序调用getSystemService(Context.SENSOR_SERVICE)方法获取Sensor Service时,实际上获取的就是SystemSensorManager的实例。 SensorEventListener接口用于注册监听的接口,应用层必须实现该接口,并重写接口的两个方法,实现对获取到的Sensor数据的处理。 android_hardware_SensorManager.cpp提供在Java层和Native层之间通信的JNI接口。 Receiver android_hardware_SensorManager.cpp的内部类,保存了一个指向SensorEventQueue的指针,利用消息队列监听服务端事件上报,可以将消息队列中获取的数据回调到Java层。 SensorManager.cppsensor在Native层的客户端,负责与服务端SensorService.cpp通信SenorEventQueue.cpp消息队列,保存了指向SensorEventConnection对象的指针,实现与SensorService之间的命令传输和数据读取。 服务端主要类SensorService.cpp服务端数据处理中心SensorEventConnectionSensorService.cpp的内部类,从BnSensorEventConnection继承来,实现接口ISensorEventConnection的一些方法,ISensorEventConnection在SensorEventQueue会保存一个指针,指向调用服务接口创建的SensorEventConnection对象BitTube.cpp在这个类中创建了管道,用于服务端与客户端读写数据SensorDevice负责与HAL进行通信,传递命令和数据。 HAL层Sensor.h是google为Sensor定义的Hal接口,单独提出去3.API调用流程当界面onResume()或者APP需要接收传感器数据的时候,应用层通过如下调用流程enable传感器,并指定接收到数据后的处理。 其中mSensorEventListener是实现SensorEventListener接口的子类对象,在该子类中必须重写onSensorChange()和onAuracyChanged(),对驱动上报的传感器数据进行处理。 这两个方法的实现可以为空,表示对收到的数据不做任何处理。 当界面切到后台或不再需要接收传感器数据时,通过调用以下方法停止接收数据,并尝试将该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的函数声明可以看出,第二个参数是对new SensorService()对象的强引用,因此当第一次构建sp强引用计数时,会调用SensorServiceonFirstRef()函数。 onFirstRef()函数主要完成以下工作初始化SensorDevice;获取HAL层传感器列表,根据支持的Hardware Sensor,初始化Virtual Sensor列表,最终形成可支持的完整传感器列表;调用run()函数启动线程。 SensorDevice是一个单实例类,当调用getInstance()时,创建对象的工作由其父类Singleton完成。 SensorDevice的构造函数中首先加载HAL的库文件,并创建SensorModule的对象。 加载库文件时会依次获取ro.hardware.sensors,ro.hardware,duct.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中保存Sensor Handle与Sensor对象指针的映射,mLastEventSeen保存Sensor Handle与Sensor Event的映射,每接收到一次传感器事件,就会将对应的event更新一次。 注册完从HAL层获取的传感器列表后,根据是否支持陀螺仪,将旋转矢量、重力、线性加速度、方向传感器注册到Virtual Sensor。 除了会将这些虚拟传感器类型添加到上面的三个集合外,还需要添加到mVirtualSensorList中。 最终,mSensorList中就保存了包含Hardware Sensor和Virtual Sensor在内的,系统所能支持的全部传感器类型,onFirstRef()函数最后调用run()函数来启动threadLooper()。 threadLooper函数的核心功能就是不断循环等待获取HAL层传过来的传感器事件,对事件进行处理后分发给客户端。 循环体中首先通过device.poll()方法等待HAL层数据,数据到来后读取到mSensorEventBuffer中。 该方法的最终实现在sensor_poll_context_t:pollEvents()方法中。 然后对当前所有的ActiveConnections做一个备份,并保存到有序Vector中。 这样做是因为在本次循环尚未执行完时,有可能其中的一些Connection就已经被移除了,特别是One-Shot类型的事件。 接下来,如果poll到的事件中存在wake-up SensorEvent,则申请一个PARTIAL_WAKE_LOCK类型的锁,阻止CPU进入休眠。 然后用mSensorEventBuffer中最新的事件更新registerSensor()时初始化的mLastEventSeen,每个handle都只保留最新的一个事件。 如果有虚拟传感器被启用,则会将Buffer中的传感器事件先传到SensorFusion中做一些处理,然后调用具体的虚拟传感器融合生成一个新的事件添加到Buffer中。 如果事件生成成功,则重新更新mLastEventSeen中对应虚拟传感器的最后一次event。 最后,通过SensorEventConnectionsendEvents()方法将Buffer中的传感器事件传输到客户端。 sendEvents函数会过滤出只属于该Connection的事件进行上报,具体处理在传感器事件获取一节再详细讨论。 至此,SensorService的启动完成。 当应用层调用getSystemService()获取传感器服务时,就能够连接到Native层的SensorService,对传感器进行控制。 getSystemService.jpg5.getDefaultSensor1TYPE_ACCELEROMETER14TYPE_MAGNETIC_FIELD_UNCALIBRATED2TYPE_MAGNETIC_FIELD15TYPE_GAME_ROTATION_VECTOR3TYPE_ORIENTATION16TYPE_GYROSCOPE_UNCALIBRATED4TYPE_GYROSCOPE17TYPE_SIGNIFICANT_MOTION5TYPE_LIGHT18TYPE_STEP_DETECTOR6TYPE_PRESSURE19TYPE_STEP_COUNTER7TYPE_TEMPERATURE20TYPE_GEOMAGNETIC_ROTATION_VECTOR8TYPE_PROXIMITY21TYPE_HEART_RATE9TYPE_GRAVITY22TYPE_TILT_DETECTOR10TYPE_LINEAR_ACCELERATION23TYPE_WAKE_GESTURE11TYPE_ROTATION_VECTOR24TYPE_GLANCE_GESTURE12TYPE_RELATIVE_HUMIDITY25TYPE_PICK_UP_GESTURE13TYPE_AMBIENT_TEMPERATURE33171011TYPE_MOTION_ACCL Framework层一共定义了26种传感器的整型常量,其中21至25是Android L新增的支持类型。 应用层可以通过引用这些字符串获得对应的传感器对象。 如果想获得这26种之外的传感器对象,可以通过在getDefaultSensor方法中直接传入该Sensor对应的type数值获取,但这种方法不便于应用层使用。 最佳方案是在Sensor.java中添加整型常量,应用层只需要引用相应的常量名,而不需要关心具体的type数值。 但Sensor.java必须确保定义的常量与所代表的传感器type值相对应,不能随便赋值。 getDefaultSensor方法用于获取指定类型的传感器对象。 如果存在多个相同类型的传感器,只返回列表中满足条件的第一个。 getDefaultSensor(int)方法在5.0之前就一直存在,但Android L上对该方法的实现进行了修改,增加了对wakeUp Sensor类型的处理。 TYPE_PROXIMITY、TYPE_SIGNIFICANT_MOTION、TYPE_TILT_DETECTOR、TYPE_WAKE_GESTURE、TYPE_GLANCE_GESTURE、TYPE_PICK_UP_GESTURE这六种类型应默认为wake-up Sensor。 如果驱动侧没有为这六种传感器添加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)就可以获取到非唤醒类型的距离传感器对象。 由于Android L之前的平台都只有getDefaultSensor(int)接口,为兼容以前的项目,应用层基本都是使用该方法获取指定类型传感器对象。 为保证应用层能够正确获取到传感器对象,驱动在配置wakeUp Sensor标识时应按照该方法指定的六种传感器实施。 6.registerSensorListener Register.jpg Register执行时主要有两大步骤一是创建framework与SensorService之间的数据通道,通过new SensorEventQueue()实现;二是将对应类型的传感器使能,通过addSensor()实现。 对于应用层而言,调用的API接口是SensorManager中的registerListener()方法,但SensorManager是一个abstract Class,主要负责将API接口提供给应用层调用,SystemSensorManager是其子类,该类中提供了方法的具体实现。 mSensorListeners是一个HashMap,保存了SensorEventListener对象与SensorEventQueue对象的对应关系。 Register开始执行时首先从mSensorListeners中检查该listener是否之前已经注册过,如果已经注册过直接调用addSensor启用Sensor,否则先创建一个SensorEventQueue对象,建立framework到Native的数据传输管道,然后再启用传感器。 因为同一个SensorEventListener对象中有可能会处理多种类型传感器的数据,所以同一个listener有可能会同多个Sensor进行绑定。 Register listener时如果发现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的内部类,该类在构造时主要进行了一些初始化参数列表工作,其中最主要的操作是new BitTube(),创建完成后,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对象进行处理。 至此,第一步new SensorEventQueue()完成。 第二步调用addSensor()方法启用传感器。 首先从mActiveSensors中检查该传感器是否已激活,如果已激活则返回false。 但是,mActiveSensors是BaseEventQueue的成员变量,不是SystemSensorManager的全局变量,每一个BaseEventQueue对象都对应一个mActiveSensors。 考虑到一个BaseEventQueue只能对应一个SensorEventListener,所以除非是mListener和Sensor对象都相同才会返回false,否则不管是同一种传感器注册了另一个Listener对象,还是同一个Listener注册到另一种传感器上,都会继续执行enableSensor。 enableSensor()会调用JNI层的nativeEnableSensor()函数,然后依次调用SensorEventQueueSensorEventConnection中的enableDisable()函数,由于注册Listener时是启用传感器,所以会执行SensorService的enable()函数,同时SensorEventConnection会将自身作为参数传递给enable()函数。 enable()函数会首先检查要启用的传感器是否已处于激活状态,如果未激活,则创建SensorRecord对象,用于管理连接到该类型传感器的SensorEventConnection对象。 创建完成后将SensorEventConnection对象保存到其中,同时将该传感器handle和SensorRecord对象添加到mActiveSensors中。 如果已激活,则只将mConnection添加到SensorRecord中,如果该传感器数据上报类型为ON_CHANGE,则立即将上一次得到的数据通过新mConnection上报。 Sensor激活状态检查完成后,将要启用的Sensor Handle保存到mConnection中,用于标识该通道可以传递哪些类型传感器的数据,然后将该mConnection添加到mActivieConnection中。 最后调用activate方法激活该传感器。 sensor是指向SensorInterface类实例的指针,不管是HardwareSensor,还是GravitySensor、OrientationSensor等Virtual Sensor都是其子类,这些子类的activate()方法最终都通过SensorDevice:activate()方法与HAL层Sensors.cpp中的sensors_poll_context_t:activate()进行关联。 不同之处在于HardwareSensor中直接调用SensorDevice:activate()激活对应类型传感器,而Virtual Sensor是通过SensorFusion:activate()间接调用,并且会同时激活A、Mag、Gyro三种传感器。 7.onSensorChange SensorService的主线程开始运行后,会通过poll()方法不断从HAL层获取数据,当获取到数据后,通过相应的SensorEventConnection对象写入到共享内存区域BitTube中,MessageQueue中会监听接收端mReceiverFd的事件,当有事件写入时,会将事件取出并回调Receiver:handleEvent()方法,接着通过JNI机制回调Java层SystemSensorManager的内部类SensorEventQueue中的dispatchSensorEvent()方法,该方法最终将数据分发给对应的SensorEventListener进行处理。 DataTransfer.jpg7.1SensorService:threadLoop()SensorService启动后,threadLoop()函数不断循环等待HAL层上报的数据。 mSensorDevice在SensoerDevice类对象构造时通过open_sensor_1()函数进行初始化,Q SensorHAL中该方法的最终实现是在sensors.cpp的open_sensors()函数。 在open_sensors()中,函数指针poll被赋值为poll_poll()函数的地址。 poll_poll()函数体内就是调用sensor_poll_context_t:pollEvents()函数,pollEvents()会依次查看每个传感器是否有事件产生,若有则通过NativeSensorManager:readEvents()方法读取事件。 遍历完全部传感器并读取到了事件,或者未遍历完全部传感器但已读取到指定数量的事件,都会将事件返回给Native层。 如果没有读取到事件,则继续下一次循环,知道读取到事件为止。 7.2SensorEventConnection:sendEvents()threadLoop中获取到HAL上报的数据后,会对数据进行判断和处理,然后通过SensorEventConnection:sendEvents()方法将数据通过对应的数据通道上报给应用层。 从下面的代码可以看出,数据会在当前所有活跃的Connection中都处理一遍,同时,如果connection中包含数据上报类型为One-Shot的传感器,则上报一次数据后,会将本数据通道自动停用。 虽然从代码看,数据在当前所有活跃的Connection中都处理了一次,但每个Connection只传递自己特定类型传感器的数据才是正解,而不是不管什么类型传感器的数据都传递一遍。 在SensorEventConnection对象中保存了一个Sensor Handle集合,标识了该Connection可以传递哪些类型传感器的数据。 由第6节流程可知,在SensorService:enabl
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 第15课 综合活动:作品展示会教学设计-2023-2024学年小学信息技术(信息科技)四年级上册粤教粤科版
- 25、节约用水教学设计-2025-2026学年小学数学六年级上册浙教版
- 2023-2024学年清华版(2012)信息技术三年级下册第二单元《 5课 锦上添花-插入剪贴画》教学设计
- 2025整形外科学同步习题及答案
- 全国清华版信息技术小学一年级下册新授课 第14课 编辑研究报告 教学设计
- 2025国家机械总院集团相关单位干部岗位招聘笔试历年参考题库附带答案
- 2025化学考试真题及答案解析
- 2026-2031中国树脂市场分析及发展策略研究预测报告
- 2025陕西西安曲江建设集团有限公司及下属公司招聘40人笔试历年常考点试题专练附带答案详解试卷3套
- 2025福建广电网络集团股份有限公司连江分公司招聘笔试历年难易错考点试卷带答案解析试卷3套
- 大学生职业生涯发展报告
- 山东省济南市(2024年-2025年小学四年级语文)统编版阶段练习((上下)学期)试卷及答案
- 复式统计表(教学设计)-2023-2024学年五年级上册数学苏教版
- 新型电力电子拓扑与控制
- 财税201758号文深度解析:工程项目预收账款财税处理大调整
- 六年级英语阅读27篇
- 2024年温州工业与能源集团招聘笔试参考题库附带答案详解
- GB/T 43803-2024科研机构评估指南
- 心肌淀粉样变护理措施
- DB21-T 2986.6-2018公共场所风险等级与安全防护 第6部分:图书场馆
- 风电运维安全生产知识
评论
0/150
提交评论