Android SensorService源码分析(二)

继续上一篇文章,继续分析关于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数据分发的流程分析完毕。
欢迎关注个人微信公众号,定期更新个人工作心得
Android SensorService源码分析(二)_第1张图片

你可能感兴趣的:(android)