传感器SensorService详细分析.docx

上传人:牧羊曲112 文档编号:5009057 上传时间:2023-05-29 格式:DOCX 页数:18 大小:350.58KB
返回 下载 相关 举报
传感器SensorService详细分析.docx_第1页
第1页 / 共18页
传感器SensorService详细分析.docx_第2页
第2页 / 共18页
传感器SensorService详细分析.docx_第3页
第3页 / 共18页
传感器SensorService详细分析.docx_第4页
第4页 / 共18页
传感器SensorService详细分析.docx_第5页
第5页 / 共18页
亲,该文档总共18页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《传感器SensorService详细分析.docx》由会员分享,可在线阅读,更多相关《传感器SensorService详细分析.docx(18页珍藏版)》请在三一办公上搜索。

1、SensorService相关架构和流程指导1.整体架构Applications层是使用传感器实现各种功能的具体应用程序,用来接收 Sensor返回的数据,并处理实现对应的UI效果和特定功能,比如翻转静音、体 感通话等功能。Framework层为应用层提供register、unRegister等接口,同时通过JNI建立 与 Native 层的联系,主要代码有 SensorManager.java 和 SystemSensorManager.java。 另外,自动转屏、自动调节亮度、距离传感器控制亮屏和灭屏等功能也是在 framework层实现。如果想用现有传感器通过算法合成其他传感器功能,也可

2、以 在本层添加,但由于不是Android原有接口,外部第三方APK无法使用。主要 代码路径为:framework/base/core/java/android/hardware/framework/base/core/jni/android_hardware_SensorManager.cppLibraries表示动态库,它封装了整个Sensor的IPC机制,如SensorManager 是客户端,SensorService是服务端,而HAL部分是封装了服务端对Kernel的直 接访问。主要代码路径为:framework/native/libs/gui (生成 libgui.so)framew

3、ork/native/services/sensorservice (生成 libsensorservice.so) hardware/qcom/sensors 或 hardware/hisense/sensors (生成 sensor.xxx.so) 驱动注册到 Kernel 的 Input Subsystem 上,然后通过 Event Device 把 Sensor 数据传到HAL层,准确说是HAL从Event读。硬件挂在I2C总线上。2.类图SensorClassDiagram.jpgSensor框架分为三个层次,客户度、服务端、HAL层,服务端负责从 HAL读取数据,并将数据写到管道中

4、,客户端通过管道读取服务端数据。客户端主要类SensorManager.java:从 android4.1 开始,SensorManager 被定义为一个 抽象类,定义了一些主要的方法,该类是应用层直接使用的类,提供给应用层的 接口。SystemSensorManagerjava 继承于 SensorManager.java 类,是客户端 消息处理的实体,应用程序调用 getSystemService(Context.SENSOR_SERVICE) 方法获取Sensor Service时,实际上获取的就是SystemSensorManager的实例。SensorEventListener接口:

5、用于注册监听的接口,应用层必须实现该 接口,并重写接口的两个方法,实现对获取到的Sensor数据的处理。android_hardware_SensorManager.cpp: 提供在 Java 层和 Native 层之 间通信的JNI接口。Receiver: android_hardware_SensorManager.cpp 的内部类,保存了一 个指向SensorEventQueue的指针,利用消息队列监听服务端事件上报,可以将 消息队列中获取的数据回调到Java层。SensorManager.cpp: sensor在Native层的客户端,负责与服务端 SensorService.cpp

6、通信SenorEventQueue.cpp: 消息队列,保存了指向 SensorEventConnection 对象的指针,实现与SensorService之间的命令传输和数据读取。服务端主要类SensorService.cpp:服务端数据处理中心SensorEventConnection : SensorService.cpp 的内 部类, 从 BnSensorEventConnection 继承来,实现接口 ISensorEventConnection 的一些方法, ISensorEventConnection在SensorEventQueue会保存一个指针,指向调用服务接 口创建的 Se

7、nsorEventConnection 对象BitTube.cpp:在这个类中创建了管道,用于服务端与客户端读写数据SensorDevice:负责与HAL进行通信,传递命令和数据。HAL层Sensor.h是google为Sensor定义的Hal接口,单独提出去3. API调用流程当界面onResume()或者APP需要接收传感器数据的时候,应用层通过如下 调用流程enable传感器,并指定接收到数据后的处理。m3eiL30rMaracer = (3eheorManagar) e2iitesz. getSyatemService 2ont巳乂二.SENSCR SCE)if (mSenaor 1=

8、 null) lumens. re q-i st er Listenerm3 匚 nm 口u. niSdte);其中 mSensorEventListener 是实现 SensorEventListener 接 口的子类对象,在 该子类中必须重写onSensorChange()和onAccuracyChanged(),对驱动上报的传 感器数据进行处理。这两个方法的实现可以为空,表示对收到的数据不做任何处 理。public iiLter face Sensor Event Listener public void on.Sen.sorCh.anged ( SensorEvent event);p

9、uJolic void orLAccuracyChangedSensor sensorint accuracy)当界面切到后台或不再需要接收传感器数据时,通过调用以下方法停止接收 数据,并尝试将该Sensor关闭。4. SensorService 启动SensorService.cpp的继承关系如上图所示,它的直接父类是BnSensorServer, BinderService 和 Thread, SensorManager.cpp 通过 Binder 机制与 SensorService.cpp 进行通信。SensorService的启动调用流程如下。应用层通过getSystemService

10、()获取注册到ServiceManager中的系统服务, SENSOR_SERVICE返回的是SystemSensorManager类的对象,该类最终会通过 Binder 方式连接到 Native 层的 SensorServiceoinstantiate()方法是SensorService从BinderService类中继承的,具体实现如 下图所示,该方法实际上就是生成了一个SensorService对象,并将其添加到 ServiceManager 中。pnkilic :void instant J.() publish. () ; static status t puJal ish. (to

11、ool allowLsolated = false J 5p sin (defaultServiceManager () J ; re turn srn-addServee (Strlngl 6 fSERVICE : : getServlceWaine ( ) / new SERVICE () f aLLowIsoLated);从addService的函数声明可以看出,第二个参数是对new SensorService()对 象的强引用,因此当第一次构建sp强引用计数时,会调用SensorService:: onFirstRef()函数。virtual sTtatus_t- addService

12、 ( const 8trimgl 6 & naine, consTt spCIBj_nderi& serrvLce t bool allowlsolated = falsa) = 0onFirstRef()函数主要完成以下工作:初始化SensorDevice;获取HAL层传 感器列表,根据支持的Hardware Sensor,初始化Virtual Sensor列表,最终形成 可支持的完整传感器列表;调用run()函数启动线程。SensorDevice是一个单实例类,当调用getInstance()时,创建对象的工作由 其父类Singleton完成。SensorDevice的构造函数中首先加载H

13、AL 的库文件,并创建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。按此顺序最先找到的库文件会最终被加载。AEIDROI D_S INGLETO_ST AT I C_INST AITCE (SensozDevice)SensQ

14、 r Devi ce:Sensr Device(J; m3enaorEeviee(0) rir.3enaDiModule (0)BCaLUS_L err = nw_geL_niCiilULe (5ENSOR5_nAR3WARE_MCDJLE_ID Ptnw_nin lul e_t const * *)拓五 ersorMo dul e ;if (inSensorttodale) err = sens d rs_0E-er_l ( &mS en s a rModu 1 e - coiimon F fimS en s o r Device J :i f -(rnSenBorDevice if (mS

15、en2otDevice-comnen . version = SENSORS_DEVICE_JIPI_VERSION_1_1 | | raS ens a i Device- c onmcn a ver s i on = SENSDRS_DEVICEI_7E ION_1_2 ALOGE ( WARNING Upgrade sensor HAL tc version 1_3;5ensor_t const* list;caujit = mSEnsazEGdulE-get sensaxs List iLSensorMQdule , ;nActiiTffitionCDiLiit - sctCapacit

16、y (c-nimt);inro raadei;lor (size_t 1=0 ; iact i va t e (reintenret_cast (mSensorDevice如果加载成功会调用sensors_open_1 ()函数去打开传感器设备,该函数的最 终实现 是在 multihal.cpp 或者 sensors.cpp 的 open_sensors()中。接着通过 get_sensors_list函数获取NativeSensorManager中的传感器列表,并依次将列表中 的传感器置为非活跃状态。SensorDevice的初始化工作完成后,SensorService的构造函数会获取HAL

17、 层的传感器列表,并将列表中的传感器逐个进行注册。其中mSensorList用于保 存SensorService中支持的全部传感器列表,mSensorMap中保存Sensor Handle 与 Sensor 对象指针的映射,mLastEventSeen 保存 Sensor Handle 与 Sensor Event 的映射,每接收到一次传感器事件,就会将对应的event更新一次。Sensor SenBorService:iegi3tei5ensor(SensorInterface* bBensorB event t event;meinset (Sevent r ( , sizeof (eve

18、nt) ;ronst SEnsor SEnsnr (s-gete:nsor ( )/ add to the sensoi list fiefjmed. t clients)mSensorList.add(sensoi;/ / add to ojr nandlE-5eziBtu Inter face ir.appingmSensorMap.addsensoi.getHandle(f b、;/ create an entxy in rnXastEven.tSeen.己rx己f mb己stEventSeen.add(senoi.getHandle(, evet;T?etnt?n BEnsor /注册

19、完从HAL层获取的传感器列表后,根据是否支持陀螺仪,将旋转矢量、 重力、线性加速度、方向传感器注册到Virtual Sensor0除了会将这些虚拟传感器 类型添加到上面的三个集合外,还需要添加到mVirtualSensorList中。最终, mSensorList中就保存了包含Hardware Sensor和Virtual Sensor在内的,系统所能 支持的全部传感器类型,Sensor SensarServi.ee : : register-Virtua 1Sensoi Sensolintetf ace * 3 )SensQi? sensor = registerSensor s J ;mV

20、irtualSenserLi5z.add( a ;re turn sensor ronFirstRef()函数最后调用 run()函数来启动 threadLooper()。threadLooper 函 数的核心功能就是不断循环等待获取HAL层传过来的传感器事件,对事件进行 处理后分发给客户端。c= device. poll(mSenBorEvencBatfer f nuiuEventMax);/ Reset sensors event t.flags to zero/ for all eventa in tne tjffer.for (int i = C ; i (inSen.sorEvent

21、Biffer z_ . flags = 1:循环体中首先通过device.poll()方法等待HAL层数据,数据到来后读取到 mSensorEventBuffer 中。该方法的最终实现在 sensor_poll_context_t:pollEvents() 方法中。Soite dVector sp activeConnect-ions;MJtex: :Autolock _1 (mLock;for (sise_t i=0 ; i nActiveConnction.B.size ( ; +i) (sp connectionfmAetiveConnect-iorLB 1 .proiaate ( if

22、 (connection 1= D (activeConnections.add(connection);然后对当前所有的ActiveConnections做一个备份,并保存到有序Vector中。 这样做是因为在本次循环尚未执行完时,有可能其中的一些Connection就已经 被移除了,特别是One-Shot类型的事件。接下来,如果poll到的事件中存在 wake-up Sensor Event,则申请一个 PARTIAL_WAKE_LOCK类型的锁,阻止 CPU 进入休眠。然后用mSensorEventBuffer中最新的事件更新registerSensor()时初始 化的mLastEven

23、tSeen,每个handle都只保留最新的一个事件。如果有虚拟传感器被启用,则会将 Buffer 中的传感器事件先传到 SensorFusion中做一些处理,然后调用具体的虚拟传感器融合生成一个新的事件添加到Buffer中。如果事件生成成功,则重新更新mLastEventSeen中对应虚拟 传感器的最后一次evento/ hajidle virtual sensorsif (count & vcoimt J 3 ens o r s_e vent_t const: * const event = ie5 e ns a rE ven t Euf f e t ;const size t ac t i

24、 ve V i_ r t ua 1S ens r Count = inActive Virtual Sensors . size J if (activeVii-tualS ens or Count J size_t k = 0;SensoTFusiQuS fusion (SensorFiasion: : ge tlnstance ( J ;if (fiiision. isEnatledJ for (sizet 1=0 ; ioizet (count J ; :i+) J fusion.process(eventi);for (size t i=C ; i= minBuf er Size J

25、ALOGE (rrbuffer too snal 1 to hold all events : Fr 书蹶,&=七藏s 3ize=r count r k f niinEiaf f erSize);bt?eak_;sensrs_event_c out;Sensorlnt-erf ace* si = niAct iveVirtualSensors .valueAt ( jj ; if (si-proces5(Sout r eventiM niS ensorEventBuf f er count + k = out;k4-+;if (kJ / record the last synthesized

26、valuesrecoidLastValueLocked(iir.Sens rEventBuf f er count r k);count: += k;/ sart tlie buffer by tizuie-staiupsi 5最后,通过 SensorEventConnection: : sendEvents()方法将 Buffer 中的传感器 事件传输到客户端。sendEvents函数会过滤出只属于该Connection的事件进行上 报,具体处理在传感器事件获取一节再详细讨论。至此,SensorService的启动完成。当应用层调用getSystemService()获取传感 器服务时,就能

27、够连接到Native层的SensorService,对传感器进行控制。getSystemService.jpg5. getDefaultSensor1TYPE_ACCELEROMETER14TYPE_MAGNETIC_FIELD_UNCALIBRATE2TYPE_MAGNETIC_FIELD15DYPE_GAME_ROTATION_VECTOR3TYPE_ORIENTATION16TYPE_GYROSCOPE_UNCALIBRATED4TYPE_GYROSCOPE17TYPE_SIGNIFICANT_MOTION5TYPE_LIGHT18TYPE_STEP_DETECTOR6TYPE_PRES

28、SURE19TYPE_STEP_COUNTER7TYPE_TEMPERATURE20TYPE_GEOMAGNETIC_ROTATION_VECT8TYPE_PROXIMITY21?Ype_heart_rate9TYPE_GRAVITY22TYPE_TILT_DETECTOR10TYPE_LINEAR_ACCELERATIO23TYPE_WAKE_GESTURE11NYPE_ROTATION_VECTOR24TYPE_GLANCE_GESTURE12TYPE_RELATIVE_HUMIDITY25TYPE_PICK_UP_GESTURE13TYPE_AMBIENT_TEMPERATU331710

29、11TYPE_MOTION_ACCLFSmework层一共定义了 26种传感器的整型常量,其中21至25是AndroidL新增的支持类型。应用层可以通过引用这些字符串获得对应的传感器对象。 如果想获得这26种之外的传感器对象,可以通过在getDefaultSensor方法中直接传入该Sensor对应的type数值获取,但这种方法不便于应用层使用。最佳方 案是在Sensor.java中添加整型常量,应用层只需要引用相应的常量名,而不需 要关心具体的type数值。但Sensor.java必须确保定义的常量与所代表的传感器 type值相对应,不能随便赋值。getDefaultSensor方法用于获取

30、指定类型的传感器对象。如果存在多个相 同类型的传感器,只返回列表中满足条件的第一个。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。如果驱动侧没 有为这六种传感器添加wa

31、ke-up标识(SENSOR_FLAG_WAKE_UP_SENSOR),或 者为其他传感器添加了 wake-up标识,通过getDefaultSensor(int)方法都无法返回 该传感器对象。puJolic Sensor getDefanLtSenscir(int typekioolean wakeUp) 1 = get Senior List (type);fcj? (Sensor sensor : 1) if (seiisor. Is-WakeUpSensor ()wakeUpre turn seiLsor;re .112211 nul 1 :getDefaultSensor(int,b

32、oolean)是5.0上新增的方法,可用于获取指定type和 wakeUp标识的传感器对象。比如8952上同时存在两种TYPE_PROXIMITY类 型传感器,一个是可唤醒,一个不可唤醒。如果用getDefaultSensor(int)只能获取 可唤醒的。但使用getDefaultSensor(int,false)就可以获取到非唤醒类型的距离传感 器对象。由于Android L之前的平台都只有getDefaultSensor(int)接口,为兼容以前的 项目,应用层基本都是使用该方法获取指定类型传感器对象。为保证应用层能够 正确获取到传感器对象,驱动在配置wakeUp Sensor标识时应按照

33、该方法指定的 六种传感器实施。6. registerSensorListenerRegister.jpgRegisters行时主要有两大步骤:一是创建framework与SensorServic之间 的数据通道,通过new SensorEventQueue实现;二是将对应类型的传感器使能, 通过addSensor实现。对于应用层而言,调用的API接口是SensorManager中的registerListener() 方法,但SensorManager是一个abstracClass主要负责将API接口提供给应 用层调用,SystemSensorManager是其子类,该类中提供了方法的具体实现

34、。SensorEventQueue cpneiiie = niSensoeListeners . get (listener); if (queue = null) Looper looper 二 (handler != null) 2 IxandlGir.getlooper () : mMaialiOoper; queue = new Sensor Event Queue (listenerj, looper this);if ( ! qrieue-. add.erisor (se-nsor, delayUs r maxEa_chReportLatencyUsT resemzedFlags)

35、 ) queuedispose (;return false;mSensorlist-ErLers . put (listenejrlF queue ;return tme;i til 朝 |return queue. a ddS ens o r (sens or f delayUs F majcBitchRepor t-LaiDencyUs T re se irveidPl ags) ; ImSensorListeners是一个 HashMap,保存了 SensorEventListene对象与 SensorEventQueue对象的对应关系。private final Ha 5 hMap

36、mSens o rLi s teners = now HaGrLMap ( ;|Register始执行时首先从mSensorListener中检查该listen是否之前已经 注册过,如果已经注册过直接调用 addSensor启用Sensor否则先创建一个 SensorEventQueue对象,建立framework到Native的数据传输管道,然后再启用传感器。因为同一个SensorEventListener对象中有可能会处理多种类型传感器的数据, 所以同一个listener有可能会同多个Sensor进行绑定。Register listener时如果发 现mSensorListener表中已经

37、存在该listener对象,则直接调用addSensor方法检 查listener本次绑定的Sensor是否已启用,如果已启用则结束本次操作,否则继 续启用本次要绑定的Sensor,但不会创建新的数据管道。也就是说同一个listener 可以被绑定到多种传感器上,但不可以被绑定到同一种类型的传感器上两次;一 个Listener只能对应一个数据通道。BaSe EVWntQll合lie 匚=二户wk looper I Sys zn = c rMan.ac = - manager) j nis cratch); mCloseGuard . open ( ,pdj_sposep );niManager

38、 = manager;SensorEventQueue 是 BaseEventQueue 的子类,在 SensorEventQueue 的构造 函数中会首先构造BaseEventQueue,通过JNI调用将该BaseEventQueue对象与 Native层进行关联,同时SensorEventQueue对象中也会保存一个对listener对象 的引用。nativelnitSensorEventQueue:static jlong natlvelnitSensorEventQueue(TEnv *jslass clazzF jobjectSeiisorblanager & mgr (sensor

39、Hanager i : get Instance () ;9p queue (irigr . c r ea teE ventQ Li&ue ();p me s sa.geQueue = android, o s tie s sageQueije_gBtidBS s ageQueue t env / jnsgQ) fif (messa geQueLi& = NTTLIi) jnThrowRuntimeExaeption (env, raMessageGueu is not initialized-11 ?return 0;Ep reaeiver = new R.ecsi.VBr (qu.EiQE

40、i/ niessageQueue t Bvant-Q/ Ecjra.tch) i receiver-i.ncstrong ( (void4-) native mi t seiYsoTEveDt/Qiieue);return long (receiver-get()J;该方法首先调用 SensorManager.cpp中 的createEventQueue()创建同 SensorService之间的数据传输通道。sp SensorManager : : CrCatCEVCntQUdlB ()sp qiieue;Mutex: : Antolock 1(mLock);while (a s ser-t

41、Sta-teLocked () = NO_ERROR-sp connection =mSens or Server-cr eat eSens or Event Connect ion ()if (connection = NULL) -continuejqueue = new Sens or Event Queue (connection.);break;return queuej |mSensorServer 是对 ISensorServer 对象的强引用,在 SensorManager 初始化 时通过getService()方法在ServiceManager中查找“sensorservic

42、e”对应的服务, 并赋值给 mSensorServer。由第4小节可知,ServiceManager中返回的就是 SensorService 实例。从 SensorService 的类图也能看出,SensorService 是ISensorServer 的子类。status_t err = getService (name, &reiSerisorServer;CreateSensorEventConnection()方法创建了一个 SensorEventConnection 对象, 并将该对象的强引用返回给SensorManager。spService : : CrCatcScnSOrEvC

43、ntConnBCtion()uid_t uid 一 IPCThreadState:self(-getCallingUid();sp reault(new SensorEventConnection(thisj mid)r rsturn result;SensorEventConnection是SensorService的内部类,该类在构造时主要进行 了一些初始化参数列表工作,其中最主要的操作是new BitTube(),创建完成后, SensorEventConnection中会保存一个对BitTube对象的强引用。ssr.sorScryice:qjcHvantconnect-: ; SC 1

44、1 SOEVCHtCOlinGCtlOn(const spi servicej nid_t uidjIu irServica (service nnuid (uid) f mwate Loc k R& f C ount (0 f mKa s Loops r C 3 lit acks (dfalse, mDead (false) * raEventCache (NULl) r niCaGheSiz,e (0 j mMaCachesize (0)(mChannel = new BitTiibe (mServ.ice-mSocket-EuezSize);DEBUG_CONNECTI ONSmEvent sRece iv&d = mEvent s Sent F romCach & = mEire ntsS ent = C ;mTot a 1 Ac ksNeedled = mTotalAclcs Received = 0;#endiBitTube是一个字节管道,可以在进程间进行数据传递。在构造BiTube对象时,首先创建一对匿名的、互相连接的Unix域套接字,然后将用于数据接收的Socket赋给mReciveFd,将用于数据发送的Socket赋给mSensorFd。VO i i Ei t. .

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号