继续上一篇文章,继续分析关于SensorService的第三和第四部分:
三: 应用注册Sensor数据监听的过程
四: sensor数据分发的过程

三 应用注册Sensor数据监听的过程。

1 SystemSensorManager 的 registerListenerImpl 函数

   protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,  int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {       synchronized (mSensorListeners) {           SensorEventQueue queue = mSensorListeners.get(listener);           if (queue == null) {               queue = new SensorEventQueue( listener, looper, this, fullClassName);               if (!queue.addSensor( sensor, delayUs, maxBatchReportLatencyUs)) {                   queue.dispose();                   return false;               }               mSensorListeners.put(listener, queue);               return true;           } else {               return queue.addSensor(sensor, delayUs,  maxBatchReportLatencyUs);           }       }   }

SensorEventListener:需要实现的监听接口,用于返回数据。
sensor: 传感器有很多,陀螺仪,接近传感,加速度,重力等等。
mSensorListeners: 以listener为key保存,SensorEventQueue对象。
SensorEventQueue: 这个类比较重要,也是这次注册的重点。在native层它还会通过SensorManager与SensorService交互创建连接( ISensorEventConnection )。 这个连接虽然是一个Binder代理对象,这个Binder对象主要用来获取数据的Socket的fd,然后创建一个Receiver对象,监听这个fd的数据,并分发接收到的数据到监听java层SystemSensorManager的SensorEventQueue中。
这个函数做如下三件事:
1.1 从mSensorListeners找到listener对应的 SensorEventQueue ,如果不存在创建SensorEventQueue对象。
1.2 把Sensor加入到SensorEventQueue中
1.3 然后把listener和对应的SensorEventQueue保存到mSensorListeners中。

2 从mSensorListeners找到listener对应的SensorEventQueue,如果不存在创建SensorEventQueue对象。SensorEventQueue继承自BaseEventQueue类,构建它的一些重要信息就在父类的构造函数中。

BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) {           nSensorEventQueue = nativeInitBaseEventQueue( manager.mNativeInstance, new WeakReference<>(this),  looper.getQueue(), mScratch, packageName, mode, manager.mContext.getOpPackageName());}

它的构造函数主要是调用Native函数nativeInitSensorEventQueue()
manager.mNativeInstance: 指向Native层的SensorManager对象。
nSensorEventQueue: 保存Native层的Receiver对象,下面会有对Receiver对象的详细介绍。

3 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz,  jlong sensorManager, jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstring packageName, jint mode) {        SensorManager* mgr = reinterpret_cast(sensorManager);        ......        spqueue(mgr->createEventQueue(clientName, mode));        ......        spmessageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);        ......        spreceiver = new Receiver(queue, messageQueue, eventQWeak, scratch);        receiver->incStrong((void*)nativeInitSensorEventQueue);        return jlong(receiver.get());   }

3.1 把地址sensorManager转换成native层SensorManager对象mgr
3.2 调用SensorManager的createEventQueue函数创建Native层SensorEventQueue对象。
3.3 获取native层messageQueue对象,以及上一步的SensorEventQueue对象创建Receiver对象。

4 SensorManager的createEventQueue函数

    spSensorManager::createEventQueue(String8 packageName, int mode) {        spqueue;        ......        spconnection = mSensorServer->createSensorEventConnection( packageName, mode, mOpPackageName);        queue = new SensorEventQueue(connection);        return queue;   }

首先通过mSensorServer的createSensorEventConnection函数返回一个connection实例是ISensorEventConnection 的binder代理对象。
然后创建native层的SensorEventQueue对象。

5 mSensorServer->createSensorEventConnection函数创建connection的流程。

   spSensorService::createSensorEventConnection(const String8& packageName, int requestedMode, const String16& opPackageName) {   uid_t uid = IPCThreadState::self()->getCallingUid();   spresult(new SensorEventConnection(this, uid, packageName, requestedMode == DATA_INJECTION, opPackageName));}

这个函数主要就是创建一个SensorEventConnection对象他是一个Binder对象,继承自BnSensorEventConnection,同时他还继承LooperCallback ,也就是他覆盖了handleEvent函数,这个函数用于处理当对应的Fd有数据可读时被回调,在Android消息机制的整理文章中,有相关介绍。
这个函数只有在Mode = DATA_INJECTION时才有用,这里暂不展开。一会儿下面还会碰到。
另外SensorEventConnection的构造函数中,主要就是创建了一个BitTube对象保存到mChannel成员变量中。

6 BitTube对象,用于进程间通信。这个类在SurfaceFlinger的同步信号中有使用,它里面创建了一个Socket对,一端用于写数据,另一端用于读数据。
Sensor的数据也就是用它把数据从SensorService传到应用进程。接下来的源码会分析BitTube的使用。

7 SensorEventQueue的创建:
创建SensorEventQueue对象使用了SensorService返回的ISensorEventConnection保存在成员变量:mSensorEventConnection中
在SensorEventQueue的onFirstRef函数中:
mSensorChannel = mSensorEventConnection->getSensorChannel();
调用Binder代理对象mSensorEventConnection的getSensorChannel函数获取他内部的BitTube对象,保存到mSensorChannel中。
总结一下4,5,6这三步:创建 第三步中3.2中 SensorEventQueue这个Binder对象,并保存到queue中,在SensorEventQueue对象内部创建了BitTube对象。
它里面有一个Socket对,用于传输数据。然后在第7步把BitTube对象保存到SensorEventQueue的mSensorChannel中。 数据接下来就看3.3中Receiver对象是如何使用这个BitTube对象中的Socket来传输数据的?

8 Receiver(queue, messageQueue, eventQWeak, scratch);
queue: SensorEventQueue刚刚创建的一会儿Receiver就要用他的BitTube对象。
messageQueue:在Android消息机制中分析过,native层MessageQueue中有一个Looper对象,它内部有一个Epoll一方面它可以监听自己进程的消息队列是否有消息写入,另一方面它也接受帮忙监听别的fd。当它监听的fd有数据的时候,就会调用设置的LooperCallback 的handleEvent函数。
eventQWeak: java层BaseEventQueue对象,当有数据来的时候就通过Jni的调用通过它把数据从Native层传到Java层。
其实把这几个参数分析完,这个对象干了一些什么事情了,Receiver的构造函数只是保存了上面这些参数,另外Receiver继承自LooperCallback,也就是他实现了handleEvent函数,最重要的函数就是他的onFirstRef函数,
virtual void onFirstRef() {
mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0, ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
}
mSensorQueue->getFd(): mSensorQueue 就是参数queue, getFd实际上调用的就是: mSensorChannel->getFd(); 第7步中说过mSensorChannel 就是BitTube对象。实际上获取的就是Socket的fd,
mMessageQueue的Looper对象的addFd函数监听 BitTube中socket的fd。
第四个参数this: Receiver 对象,前面说过Receiver继承自LooperCallback也就是说当Looper监听的BitTube的fd有数据发送过来的时候,会调用Receiver的hanleEvent函数。

总结一下:第8步是非常重要的一步,它构建了Receiver对象,同时把SensorService创建的SensorEventConnection对象中BitTube的fd加入到当前进程的Looper中监听起来,当有数据发送过来的时候,会回调Receiver的hanleEvent函数,然后通过Java层的BaseEventQueue,通过JNI的调用把数据分发到应用,具体在分发的流程中分析。

9 添加第5步通过SensorService创建的SensorEventConnection到SensorService的成员变量mActiveConnections中。这也是分发过程中重要的一步,分发的时候就是从mActiveConnections读取SensorEventConnection,然后通过它内部的BitTube的fd写入数据的。
回到第1步:如下代码:
queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);

public boolean addSensor( Sensor sensor, int delayUs, int maxBatchReportLatencyUs) {           int handle = sensor.getHandle();           if (mActiveSensors.get(handle)) return false;           mActiveSensors.put(handle, true);           addSensorEvent(sensor);           if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) {           ......           }           return true;       }

handle: sensor在sensor列表的位置。
mActiveSensors: 保存了listener已经注册了的哪些类型的sensor
addSensorEvent()函数: 创建一个SensorEvent,以handle为key 保存到SensorEventQueue的成员变量mSensorsEvents中。

10 enableSensor(sensor, delayUs, maxBatchReportLatencyUs)函数。
private int enableSensor(Sensor sensor, int rateUs, int maxBatchReportLatencyUs) {
return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs, maxBatchReportLatencyUs);
}
nSensorEventQueue: 第2步中初始化的,表示native层的Receiver对象的地址。
sensor.getHandle(): 标记当前需要Enable哪一个Sensor,有人监听了这个Sensor的数据当然要Enable它。
然后调用Native函数nativeEnableSensor()

11 nativeEnableSensor()函数

    static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us, jint maxBatchReportLatency) {        spreceiver(reinterpret_cast(eventQ));        return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency, 0);    }

把参数eventQ转换成receiver对象,然后获取SensorEventQueue对象,再调用他的enableSensor()函数。
在第7步创建SensorEventQueue对象的时候,使用了Binder对象ISensorEventConnection。
这个函数其实就是调用这个Binder对象ISensorEventConnection的enableDisable(sensor->getHandle(), true, 0, 0, false)
因为他是一个Binder对象,这里有一次夸进程的调用。到了SensorService类中。

12 SensorEventConnection的enableDisable函数:
这个函数根据参数enabled调用了SensorService的enable/disable函数。就目前的逻辑我们分析enable函数:
err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs, reservedFlags, mOpPackageName);
this:SensorEventConnection对象

13  status_t SensorService::enable(const sp& connection, int handle, ...) {       ......       if (connection->addSensor(handle)) {            if (mActiveConnections.indexOf(connection) < 0) {                mActiveConnections.add(connection);            }           ......   }

这个函数比较长,这里重点只关注分发过程中重要的一步,那就是把SensorEventConnection添加到mActiveConnections。
到这里这个监听的过程就分析完了。

四: sensor数据分发的过程

在SensorService服务的启动过程中我们有分析到,SensorService这个服务他不仅是一个Binder对象,也是一个线程。当他作为线程启动后,他的threadLoop函数也会执行,开始获取sensor的数据,然后向上分发数据。
接下来就从SensorService的threadLoop函数开始来分析Sensor数据的分发流程。
1 SensorService的threadLoop函数

bool SensorService::threadLoop(){   ......   //获取SensorDevice,在SensorService启动的部分中分析过,他包含了Hal层,以及控制和获取Sensor硬件的数据   SensorDevice& device(SensorDevice::getInstance());   ......   do {       //通过前面获取的device对象从Sensor中读取数据保存到mSensorEventBuffer中       ssize_t count = device.poll(mSensorEventBuffer, numEventMax);       ......       //这里是把注册监听流程13步中的mActiveConnections读取到activeConnections中。前面分析过这个里面保存的是SensorEventConnection这个Binder对象。       SortedVector< sp> activeConnections;       populateActiveConnections(&activeConnections);       ......       //记录Sensor最近的数据,它里面为每一个sensor创建了一个循环Buffer,保存Sensor最近的10条数据。       recordLastValueLocked(mSensorEventBuffer, count);       //处理虚拟sensor 这一部分代码我省略了,给出一些关键代码以及做的事情。       1  通过SensorFusion.process(sensor融合)计算从Sensor读取的每一条数。       2  遍历虚拟sensor (mActiveVirtualSensors),调用SensorInterface.process输出一条新的Sensor数据sensors_event_t,保存到mSensorEventBuffer中。          这条新的数据是通过sensor融合计算得到数据和增加一些各自虚拟sensor的计算和标记得到的。       3  recordLastValueLocked 记录虚拟sensor最近产生的数据。       ......//其实上面都是从sensor读取数据后,对数据做一些处理。       //遍历activeConnections,然后调用SensorEventConnection的sendEvents函数开始数据的分发。       size_t numConnections = activeConnections.size();       for (size_t i=0 ; i < numConnections; ++i) {           if (activeConnections[i] != 0) {               activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,                       mMapFlushEventsToConnections);       ......           }       }   } while (!Thread::exitPending());}

这个函数的重点部分已经标记,下面重点分析分发函数SensorEventConnection的sendEvents

2 SensorEventConnection的sendEvents函数:
这个函数比较长,主要在分发sensor数据之前会对一些数据做处理。
比如说:如果某一个Sensor,并没有任何应用监听他的数据,所以需要过滤掉这些数据,另外还有一些延迟刷新的处理。
我们这里重点关于分发的流程中的关键代码,其他的都省略了。

status_t SensorService::SensorEventConnection::sendEvents(       sensors_event_t const* buffer, size_t numEvents,       sensors_event_t* scratch,       SensorEventConnection const * const * mapFlushEventsToConnections) {   ......   ssize_t size = SensorEventQueue::write(mChannel, reinterpret_cast(scratch), count);   ......}

buffer: 实际上就是(mSensorEventBuffer)从Sensor读取的数据。
numEvents: buffer数据的大小。
scratch: 实际上就是(mSensorEventScratch)保存过滤后的数据,也就是需要分发的sensor数据。
mChannel: BitTube对象,在注册监听的流程中分析过他内部有一个socket对,用于进程间通信的,其中他的读数据端fd在监听流程第8步中,被加入到需要Sensor数据进程的Looper对象中监听。
当往BitTube对象的写数据的fd写入数据的时候,应用进程的Looper监听到有数据可读就会调用,在监听的时候设置的Callback对象,这个Callback对象就是Receiver对象,他的hanleEvent函数就会被调用。
SensorEventQueue::write这个函数就比较简单最终会调用BitTube的sendObjects函数把需要分发的Sensor数据scratch写入fd。
这个时候Receiver的handleEvent函数被调用。

3 Receiver的handleEvent函数:

   virtual int handleEvent(int fd, int events, void* data) {       spq = reinterpret_cast(data);       ScopedLocalRefreceiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));       ssize_t n;       ASensorEvent buffer[16];       while ((n = q->read(buffer, 16)) > 0) {           for (int i=0 ; i"" i++)="" {<="" span="">                //省略...计步器单位转换相关               if (buffer[i].type == SENSOR_TYPE_META_DATA) {                   // 批量处理完成的一个通知,具体逻辑这里不分析。               } else {                   int8_t status;                   //省略...处理status参数                   if (receiverObj.get()) {                       env->CallVoidMethod(receiverObj.get(), gBaseEventQueueClassInfo.dispatchSensorEvent,                                           buffer[i].sensor, mScratch, status, buffer[i].timestamp);                   }               }           }           ......       }        ......       return 1;   }

*data: SensorEventQueue对象,他的成员变量mSensorChannel是BitTube对象和第2步中的mChannel是同一个对象,第2步用BitTube的写fd写入sensor数据,这里就用Bittube的读fd读sensor数据。
mReceiverWeakGlobal: java层 BaseEventQueue对象,监听注册流程中第2步,调用native函数是用this作为参数传入的。
gBaseEventQueueClassInfo: 指向Java层的BaseEventQueue类。
gBaseEventQueueClassInfo. dispatchSensorEvent: 指向Java层的BaseEventQueue类的dispatchSensorEvent函数。
其实这里主要就是通过JNI调用Java层BaseEventQueue的dispatchSensorEvent函数。
实际调用的是 BaseEventQueue的子类SensorEventQueue的dispatchSensorEvent函数。

4 java层数据分发SensorEventQueue的dispatchSensorEvent函数。

   protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,  long timestamp) {       //从SystemSensorManager中通过handle取出sensor       final Sensor sensor = mManager.mHandleToSensor.get(handle);           SensorEvent t = null;           synchronized (mSensorsEvents) {         //检查当前listener是否监听的handle对应sensor                   t = mSensorsEvents.get(handle);           }           //如果没有监听直接返回。       if (t == null) {               return;           }           //如果监听了则复制数据         System.arraycopy(values, 0, t.values, 0, t.values.length);           t.timestamp = timestamp;           t.accuracy = inAccuracy;           t.sensor = sensor;           //通知精度发生变化       final int accuracy = mSensorAccuracies.get(handle);           if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {               mSensorAccuracies.put(handle, t.accuracy);               mListener.onAccuracyChanged(t.sensor, t.accuracy);           }       //mListener是应用注册的时候实现的接口,这里就调用它的onSensorChanged函数把数据传给应用。       mListener.onSensorChanged(t);       }

到这里sensor数据分发的流程分析完毕。
欢迎关注个人微信公众号,定期更新个人工作心得

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  4. Android(安卓)Intent 三解决
  5. Android(安卓)Handler类消息传递机制(三)不同类中使用Handler
  6. Android从服务器端接收json数据并解析的代码
  7. 彩信对象android(5)_发彩信操作
  8. [Android开发]Android(安卓)重要组件 之 Intent
  9. Android(安卓)Jackson 概述

随机推荐

  1. Android应用程序请求SurfaceFlinger服务
  2. Android(安卓)Measure 体系简单总结
  3. Android实现全屏显示的方法 固定横屏或者
  4. 玩转Android---UI篇---TextView(文本框)
  5. Android(安卓)Property System | Android
  6. Android:ANT打包常见问题简述
  7. Android(安卓)Studio 1.0 苹果电脑安装配
  8. Android布局优化(一)LayoutInflate — 从布
  9. Android(安卓)2.3用户增长到10%
  10. Android菜单详解(二)——创建并响应选项菜