1.前言
本篇文档主要分析安卓 Sensor框架Native层如何实现SensorEvent的分发,有何优秀设计点可以借鉴,有何缺点可以规避。下面是我分析的主要源码的路径:
| 语言 | 路径 |
|---|---|
| Java | frameworks/base/core/java/android/hardware/SystemSensorManager.java |
| C++ | frameworks/base/core/jni/android_hardware_SensorManager.cpp |
| C++ | hardware/libhardware/include/hardware/sensors.h |
| C++ | hardware/libhardware/include/hardware/sensors-base.h |
| C++ | frameworks/native/libs/sensor/* |
| C++ | frameworks/native/services/sensorservice/SensorService.cpp |
| C++ | frameworks/native/services/sensorservice/SensorEventConnenction.cpp |
2.传感器堆栈
下图显示了Android传感器组件堆栈。各个组件仅可与其上方和下方紧邻的组件通信,控制信号从应用向下流向传感器,数据从传感器向上流向应用。<br /><br />**图1**.Android 传感器堆栈层级以及各自的所有者
2.1 SDK
应用通过Sensor SDK API访问传感器。SDK包含列出可用传感器和注册监听传感器数据的函数。在注册到传感器时,应用可以指定自己的首选采样率和延迟要求。
2.2 Framework层
Sensor Framework负责将多个应用关联到HAL。HAL本身是单一客户端。如果框架级别没有发生这种多路复用,则任何指定时间内每个传感器都只能被一个应用访问。
- 当第一个应用注册到传感器时,框架会向HAL发送请求以激活传感器。
- 当其他应用注册到相同的传感器时,框架会考虑每个应用的要求,并将更新的已请求参数发送到HAL。
1.采样率将是请求的采用率的最大值,这意味着一些应用接收事件的频率会高于所请求的频率
2.最大报告延迟将是请求的延迟的最小值。如果某个应用的最大报告延迟是0,若它请求传感器,则所有应用将以连续模 式从该传感器接收事件,即使某些应用请求传感器时的最大报告延迟不是0也是如此。
- 当注册到某个传感器的最后一个应用取消注册后,框架会向HAL发送请求以停用该传感器,从而避免不必要的功耗。
2.3HAL
Sensors Hardware Abstraction Layer(HAL)API是硬件驱动程序和Android框架之间的接口。它包含一个HAL接口sensors.h(hardware/libhardware/include/hardware/sensors.h)和一个被称为sensors.cpp的HAL实现。
接口由Android和AOSP贡献者定义,并由设备制造商提供实现。3.Native类的调用关系和启动流程
3.1调用关系
下图大致展示了Sensor框架各个主要类的调用关系:
3.2 启动流程
Sensor框架在系统中主要分两条路线启动:
一条是系统启动时,SensorService的启动,另一条是系统启动时SensorManager.java启动连带着SensorManager.cpp的启动:3.2.1 SensorService的启动
SensorService是在system_server启动的时候,被system_server启动的,
代码路径:frameworks/base/services/java/com/android/server/SystemServer.java ```java
private void startBootstrapServices() { //…… mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> { TimingsTraceLog traceLog = new TimingsTraceLog( SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER); traceLog.traceBegin(START_SENSOR_SERVICE); startSensorService();//调用JNI接口 traceLog.traceEnd(); }, START_SENSOR_SERVICE);
//......
}
startSensorService是一个JNI方法,其对应的C++实现如下:```cpp/** JNI registration.*/static const JNINativeMethod gMethods[] = {/* name, signature, funcPtr *///这边先将该接口注册,后面给system_server调用{ "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService }{ "startHidlServices", "()V", (void*) android_server_SystemServer_startHidlServices },};//在这儿创建sensorservicestatic void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {char propBuf[PROPERTY_VALUE_MAX];property_get("system_init.startsensorservice", propBuf, "1");if (strcmp(propBuf, "1") == 0) {SensorService::instantiate();}}
从上面源码看出,SensorService实例是通过调用SensorService::instantiate()方法创建的,此方法来源于SensorService的父类BinderService,所以实质上是调用BinderService::instantiate()来创建实例,而BinderService::instantiate()方法内部仅仅调用了BinderService::publish(),相关方法源码如下:
//这边SERVICE为SensorService类型template<typename SERVICE>class BinderService{//......public:static status_t publish(bool allowIsolated = false,int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {sp<IServiceManager> sm(defaultServiceManager());//创建SensorService实例并且添加到ServiceManagereturn sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,dumpFlags);}static void instantiate() { publish(); }//......};
看SensorService的构造函数,主要是创建了UidPolicy对象,此对象功能是管理待机sensor的行为:
SensorService::SensorService(): mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),mWakeLockAcquired(false) {mUidPolicy = new UidPolicy(this);}
在BinderService::publish()函数中创建SensorService实例时,会调用onFirstRef()方法,这个方法里,首先创建并获取SensorDevice实例,获取vendor层注册的sensor数据,然后遍历每个sensor并将它们注册到SensorList里边,创建并运行一个SensorEventAckReceiver线程,再创建一个线程运行SensorService::threadLoop(),其代码如下:
void SensorService::onFirstRef() {SensorDevice& dev(SensorDevice::getInstance());//创建并获取SensorDevice实例sHmacGlobalKeyIsValid = initializeHmacKey();if (dev.initCheck() == NO_ERROR) {sensor_t const* list;ssize_t count = dev.getSensorList(&list);//获取vendor层注册的sensor 数目if (count > 0) {ssize_t orientationIndex = -1;bool hasGyro = false, hasAccel = false, hasMag = false;uint32_t virtualSensorsNeeds =(1<<SENSOR_TYPE_GRAVITY) |(1<<SENSOR_TYPE_LINEAR_ACCELERATION) |(1<<SENSOR_TYPE_ROTATION_VECTOR) |(1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) |(1<<SENSOR_TYPE_GAME_ROTATION_VECTOR);//遍历每个sensor并将其注册到SensorList里边for (ssize_t i=0 ; i<count ; i++) {bool useThisSensor=true;switch (list[i].type) {case SENSOR_TYPE_ACCELEROMETER:hasAccel = true;break;case SENSOR_TYPE_MAGNETIC_FIELD:hasMag = true;break;case SENSOR_TYPE_ORIENTATION:orientationIndex = i;break;case SENSOR_TYPE_GYROSCOPE:case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:hasGyro = true;break;case SENSOR_TYPE_GRAVITY:case SENSOR_TYPE_LINEAR_ACCELERATION:case SENSOR_TYPE_ROTATION_VECTOR:case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:case SENSOR_TYPE_GAME_ROTATION_VECTOR:if (IGNORE_HARDWARE_FUSION) {useThisSensor = false;} else {virtualSensorsNeeds &= ~(1<<list[i].type);}break;}if (useThisSensor) {//将HAL层的sensor_t类型结构体,存在HardwareSensor类里边,//进而在SensorList类里边通过map将handle和HardwareSensor一起存储起来,registerSensor( new HardwareSensor(list[i]) );}}// it's safe to instantiate the SensorFusion object here// (it wants to be instantiated after h/w sensors have been// registered)SensorFusion::getInstance();//融合虚拟sensor的一些逻辑处理,这些不是重点,可以先不管//所谓融合sensor,就是虚拟一个sensor,数据是拿一个或多个实际sensor的数据通过各种算法运算处理出来的,//比如手机里边的自动转屏功能,就是用加速度数据算出来的。//一般这些虚拟sensor需要一个算法一直在跑,若直接跑在AP端功耗很高,//手机厂家都是将其实现在协处理器里边,比如高通骁龙845、855的slpi,//而不是直接用google在framework实现的那套算法,if (hasGyro && hasAccel && hasMag) {// Add Android virtual sensors if they're not already// available in the HALbool needRotationVector =(virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) != 0;registerSensor(new RotationVectorSensor(), !needRotationVector, true);registerSensor(new OrientationSensor(), !needRotationVector, true);bool needLinearAcceleration =(virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;registerSensor(new LinearAccelerationSensor(list, count),!needLinearAcceleration, true);// virtual debugging sensors are not for userregisterSensor( new CorrectedGyroSensor(list, count), true, true);registerSensor( new GyroDriftSensor(), true, true);}if (hasAccel && hasGyro) {bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;registerSensor(new GravitySensor(list, count), !needGravitySensor, true);bool needGameRotationVector =(virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);}if (hasAccel && hasMag) {bool needGeoMagRotationVector =(virtualSensorsNeeds & (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) != 0;registerSensor(new GeoMagRotationVectorSensor(), !needGeoMagRotationVector, true);}mWakeLockAcquired = false;mLooper = new Looper(false);const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;mSensorEventBuffer = new sensors_event_t[minBufferSize];//创建存储sensor数据的buffer,可以存储256个数据mSensorEventScratch = new sensors_event_t[minBufferSize];mMapFlushEventsToConnections = new wp<const SensorEventConnection> [minBufferSize];mCurrentOperatingMode = NORMAL;mNextSensorRegIndex = 0;for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {mLastNSensorRegistrations.push();//这个用来保存应用开关sensor的记录,后面 dumpsys sensorservice dump出来方便debug问题}mInitCheck = NO_ERROR;//创建并运行一个SensorEventAckReceiver 线程//这个loop线程用来不断检测是否需要持有wakelockmAckReceiver = new SensorEventAckReceiver(this);mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);//在run里边调用SensorEventAckReceiver::threadLoop()方法,//通过创建一个线程运行SensorService::threadLoop(),run("SensorService", PRIORITY_URGENT_DISPLAY);// priority can only be changed after runenableSchedFifoMode();//降低主线程调度优先级// Start watching UID changes to apply policy.mUidPolicy->registerSelf();//这边mUidPolicy将自己注册到uid待机管理里边,后面应用待机行为发生变化时其接口会通过多态被回调}}}
下面来看SensorService::threadLoop()方法:
bool SensorService::threadLoop() {ALOGD("nuSensorService thread starting...");// each virtual sensor could generate an event per "real" event, that's why we need to size// numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT. in practice, this is too// aggressive, but guaranteed to be enough.const size_t vcount = mSensors.getVirtualSensors().size();const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;const size_t numEventMax = minBufferSize / (1 + vcount);//比如这边有vcount个虚拟的 sensor跑在framework,//那么比较极端的情况下每从HAL取numEventMax个数据,这边vcount个sensor会各生成numEventMax个数据,//而mSensorEventBuffer 最多只能容纳 MAX_RECEIVE_BUFFER_EVENT_COUNT个数据,//所以 numEventMax = minBufferSize / (1 + vcount);SensorDevice& device(SensorDevice::getInstance());const int halVersion = device.getHalDeviceVersion();do {//通过SensorDevice往HAL层取数据, 若没有数据的时候就一直阻塞(这个由前面说的第三方SO库实现)//一般在该so库的poll里边,可以采用c++标准实现的queue::pop(),来获取数据,没数据时就一直阻塞,//当驱动有数据上来时,另外一个线程将sensor数据往这个队列里边queue::pop就行了ssize_t count = device.poll(mSensorEventBuffer, numEventMax);if (count < 0) {ALOGE("sensor poll failed (%s)", strerror(-count));break;}// Reset sensors_event_t.flags to zero for all events in the buffer.for (int i = 0; i < count; i++) {mSensorEventBuffer[i].flags = 0;}// Make a copy of the connection vector as some connections may be removed during the course// of this loop (especially when one-shot sensor events are present in the sensor_event// buffer). Promote all connections to StrongPointers before the lock is acquired. If the// destructor of the sp gets called when the lock is acquired, it may result in a deadlock// as ~SensorEventConnection() needs to acquire mLock again for cleanup. So copy all the// strongPointers to a vector before the lock is acquired.SortedVector< sp<SensorEventConnection> > activeConnections;populateActiveConnections(&activeConnections);Mutex::Autolock _l(mLock);// Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The// rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,// sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should// not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and// releasing the wakelock.bool bufferHasWakeUpEvent = false;for (int i = 0; i < count; i++) {if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {bufferHasWakeUpEvent = true;break;}}//若有wakeup 类型sensor上报的数据就持有wakelockif (bufferHasWakeUpEvent && !mWakeLockAcquired) {setWakeLockAcquiredLocked(true);}recordLastValueLocked(mSensorEventBuffer, count);//将事件保存下来,后面可以用dumpsys sensorservice dump出来方便分析问题// 暂时先忽略handle virtual sensor,dynamic sensor部分// Send our events to clients. Check the state of wake lock for each client and release the// lock if none of the clients need it.bool needsWakeLock = false;size_t numConnections = activeConnections.size();for (size_t i=0 ; i < numConnections; ++i) {if (activeConnections[i] != 0) {//通过SensorEventConnection 将数据通过socket发送给应用activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,mMapFlushEventsToConnections);needsWakeLock |= activeConnections[i]->needsWakeLock();// If the connection has one-shot sensors, it may be cleaned up after first trigger.// Early check for one-shot sensors.if (activeConnections[i]->hasOneShotSensors()) {cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,count);}}}//若还有wake up 类型的sensor报上来的数据的话,需要继续持有wakelockif (mWakeLockAcquired && !needsWakeLock) {setWakeLockAcquiredLocked(false);}} while (!Thread::exitPending());ALOGW("Exiting SensorService::threadLoop => aborting...");abort();return false;}
该方法就是用SensorDevice循环去HAL层取数据,若无数据则阻塞当前线程,若有数据,则封装SensorEventConnection发送出去。至此SensorService已经启动了。
3.2.2 SensorManager的启动流程
从前一篇分析安卓Sensor 框架 Java API层的源码中我们知道,SystemSensorManager继承并实现SensorManager的虚方法,应用通过调用SensorManger的方法来达到其监听sensor数据的需求,而实际功能的实现者是SystemSensorManager,且SystemSensorManager中负责和Native层的SensorManager交互。安卓系统开机时在<br />frameworks/base/core/java/android/app/SystemServiceRegistry.java中创建SystemSensorManger实例:
registerService(Context.SENSOR_SERVICE, SensorManager.class,new CachedServiceFetcher<SensorManager>() {@Overridepublic SensorManager createService(ContextImpl ctx) {return new SystemSensorManager(ctx.getOuterContext(),ctx.mMainThread.getHandler().getLooper());}});
然后跳转到SystemSensorManager的构造方法中:
public SystemSensorManager(Context context, Looper mainLooper) {synchronized (sLock) {if (!sNativeClassInited) {sNativeClassInited = true;nativeClassInit();//native层offset初始化,没做什么其他事情}}Log.e("======>lkh", Log.getStackTraceString(new Throwable()));mMainLooper = mainLooper;mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;mContext = context;mNativeInstance = nativeCreate(context.getOpPackageName());//mNativeInstance 保存native创建的 c++对象 SensorManager的引用,//该对象通过getOpPackageName()返回的结果作为参数创建,并且2者保存在一个map里边,//注意,此SensorManager为native层c++实现的,非面向应用用Java实现的SensorManager// initialize the sensor listfor (int index = 0;; ++index) {Sensor sensor = new Sensor();if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break;mFullSensorsList.add(sensor);mHandleToSensor.put(sensor.getHandle(), sensor);}//获取SesorService的sensor list里边的所有sensor,每个sensor创建一个对应的java层的Sensor对象,//并保存到链表里边,并将sensor handle和sensor一并保存到map里边}
在加锁的情况下,如果没有初始化过Native层的类,则调用nativeClassInit() JNI方法初始化,调用nativeCreate()方法初始化SensorManager.cpp的实例,再调用nativeGetSensorAtIndex() jni方法初始化sensor列表,以上分析可知,当SystemSensorManager初始化时,SensorManager.cpp同时也初始化了。
static jlongnativeCreate(JNIEnv *env, jclass clazz, jstring opPackageName){ScopedUtfChars opPackageNameUtf(env, opPackageName);return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));}
接下来跳入Native SensorManager的构造函数中:
SensorManager::SensorManager(const String16& opPackageName): mSensorList(0), mOpPackageName(opPackageName), mDirectConnectionHandle(1) {// okay we're not locked here, but it's not needed during constructionassertStateLocked();}status_t SensorManager::assertStateLocked() {bool initSensorManager = false;if (mSensorServer == NULL) {initSensorManager = true;} else {// Ping binder to check if sensorservice is alive.status_t err = IInterface::asBinder(mSensorServer)->pingBinder();if (err != NO_ERROR) {initSensorManager = true;}}if (initSensorManager) {waitForSensorService(&mSensorServer);LOG_ALWAYS_FATAL_IF(mSensorServer == nullptr, "getService(SensorService) NULL");class DeathObserver : public IBinder::DeathRecipient {SensorManager& mSensorManager;virtual void binderDied(const wp<IBinder>& who) {ALOGW("sensorservice died [%p]", who.unsafe_get());mSensorManager.sensorManagerDied();}public:explicit DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }};mDeathObserver = new DeathObserver(*const_cast<SensorManager *>(this));IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);mSensors = mSensorServer->getSensorList(mOpPackageName);size_t count = mSensors.size();mSensorList =static_cast<Sensor const**>(malloc(count * sizeof(Sensor*)));LOG_ALWAYS_FATAL_IF(mSensorList == NULL, "mSensorList NULL");for (size_t i=0 ; i<count ; i++) {mSensorList[i] = mSensors.array() + i;}}return NO_ERROR;}
上面代码主要做了3件事情:
- 等待SensorService起来,获取到其指针
- 注册一个DeathObserver,当sensorManagerDied()时,做一些清理操作
-
3.3 Sensor数据的分发
接下来分析SensorService如何将sensor数据分发到应用,上面SensorService启动时,我们知道SensorService启动了一个线程去执行threadLoop方法,这个方法首先调用SensorDevice::getInstance()方法,获取其实例引用,接下来就进入了一个调用SensorDevice::poll()方法的do while循环中,SensorDevice在其中扮演了十分重要的角色,主要通过该类从HAL层取数据,下面是SensorDevice的部分源码: ```cpp SensorDevice::SensorDevice()
: mHidlTransportErrors(20), mRestartWaiter(new HidlServiceRegistrationWaiter()) {
//通过hidl与HAL层建立连接 if (!connectHidlService()) {
return;
}
//获取开机时前面所说的第三方SO库注册的sensor,这个SO库一般就是直接与驱动进行通信对实际sensor进行开关和数据获取了, //比如高通骁龙855的sensors.ssc.so通过qmi与slpi进行通信。 //这些sensor_t 类型的结构体,需要第三方的so库里边自己实现,每个结构体对象存储一个sensor的信息 checkReturn(mSensors->getSensorsList(
[&](const auto &list) {const size_t count = list.size();mActivationCount.setCapacity(count);Info model;for (size_t i=0 ; i < count; i++) {sensor_t sensor;convertToSensor(list[i], &sensor);// Sanity check and clamp power if it is 0 (or close)if (sensor.power < minPowerMa) {ALOGE("Reported power %f not deemed sane, clamping to %f",sensor.power, minPowerMa);sensor.power = minPowerMa;}mSensorList.push_back(sensor);//将HAL层注册的sensor保存起来,具体如何注册的,后面分析sensor HAL层部分再分析//保存该sensor的handle,具体数值是在前面所说的第三方SO库决定的,一般是从1开启按顺序叠加mActivationCount.add(list[i].sensorHandle, model);checkReturn(mSensors->activate(list[i].sensorHandle, 0 /* disable */));//关闭该sensor,以防开着没用漏电}}));
}
bool SensorDevice::connectHidlService() { // SensorDevice will wait for HAL service to start if HAL is declared in device manifest. size_t retry = 10;
while (retry-- > 0) {//......//通过hidl获取 android.hardware.sensors@1.0-servicemSensors = ISensors::getService();if (mSensors == nullptr) {// no sensor hidl service foundbreak;}//.......}return (mSensors != nullptr);
}
与HAL层如何交互的分析已经远远超出我负责的范畴了,这里不做深入分析。我们只需知道Native层的Sensor数据是通过SensorDevice去HAL取得的就行了。当数据上来后,通过做一些判断和处理然后再分发给应用,其中判断处理包括:是否应该丢弃数据,是否是flush数据,是否需要将数据给融合sensor,应用是否已经关闭该sensor等,处理后,通过SensorService::SensorEventConnection::sendEvents将数据发出,senEvent()函数代码如下:```cppstatus_t SensorService::SensorEventConnection::sendEvents(sensors_event_t const* buffer, size_t numEvents,sensors_event_t* scratch,wp<const SensorEventConnection> const * mapFlushEventsToConnections) {// filter out events not for this connectionsensors_event_t* sanitizedBuffer = nullptr;int count = 0;Mutex::Autolock _l(mConnectionLock);if (scratch) {size_t i=0;while (i<numEvents) {//每个数据琢一处理int32_t sensor_handle = buffer[i].sensor;if (buffer[i].type == SENSOR_TYPE_META_DATA) {ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",buffer[i].meta_data.sensor);// Setting sensor_handle to the correct sensor to ensure the sensor events per// connection are filtered correctly. buffer[i].sensor is zero for meta_data// events.sensor_handle = buffer[i].meta_data.sensor;}ssize_t index = mSensorInfo.indexOfKey(sensor_handle);//enable 一个sensor时,会保存该sensor的handle//确认一下若该sensor已经被disable了,那么就没有必要将该sensor的数据给到应用了//或者该应用没有注册该sensor的话,也是直接过滤掉// Check if this connection has registered for this sensor. If not continue to the// next sensor_event.if (index < 0) {++i;continue;}FlushInfo& flushInfo = mSensorInfo.editValueAt(index);// Check if there is a pending flush_complete event for this sensor on this connection.if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&mapFlushEventsToConnections[i] == this) {flushInfo.mFirstFlushPending = false;ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",buffer[i].meta_data.sensor);++i;continue;}// If there is a pending flush complete event for this sensor on this connection,// ignore the event and proceed to the next.if (flushInfo.mFirstFlushPending) {++i;continue;}//过滤掉flush的数据后,将要给到应用的数据拷到scratchdo {// Keep copying events into the scratch buffer as long as they are regular// sensor_events are from the same sensor_handle OR they are flush_complete_events// from the same sensor_handle AND the current connection is mapped to the// corresponding flush_complete_event.if (buffer[i].type == SENSOR_TYPE_META_DATA) {if (mapFlushEventsToConnections[i] == this) {scratch[count++] = buffer[i];}} else {// Regular sensor event, just copy it to the scratch buffer.//若为false,即应用进入idle,那么就不将数据装进scratch在通过scratch给到应用,//否则就装进去if (mHasSensorAccess) {scratch[count++] = buffer[i];}}i++;} while ((i<numEvents) && ((buffer[i].sensor == sensor_handle &&buffer[i].type != SENSOR_TYPE_META_DATA) ||(buffer[i].type == SENSOR_TYPE_META_DATA &&buffer[i].meta_data.sensor == sensor_handle)));}} else {//这边不会走到不用管,感觉google这段代码有点多余哈哈if (mHasSensorAccess) {scratch = const_cast<sensors_event_t *>(buffer);count = numEvents;} else {scratch = sanitizedBuffer = new sensors_event_t[numEvents];for (size_t i = 0; i < numEvents; i++) {if (buffer[i].type == SENSOR_TYPE_META_DATA) {scratch[count++] = buffer[i++];}}}}sendPendingFlushEventsLocked();// Early return if there are no events for this connection.if (count == 0) {delete sanitizedBuffer;//可能遇到空指针? free 已经做了判断了return status_t(NO_ERROR);}#if DEBUG_CONNECTIONSmEventsReceived += count;#endif//将最新的数据缓存到mEventCache,后面可以dump出来debugif (mCacheSize != 0) {// There are some events in the cache which need to be sent first. Copy this buffer to// the end of cache.if (mCacheSize + count <= mMaxCacheSize) {memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));mCacheSize += count;} else {// Check if any new sensors have registered on this connection which may have increased// the max cache size that is desired.if (mCacheSize + count < computeMaxCacheSizeLocked()) {reAllocateCacheLocked(scratch, count);delete sanitizedBuffer;return status_t(NO_ERROR);}// Some events need to be dropped.int remaningCacheSize = mMaxCacheSize - mCacheSize;if (remaningCacheSize != 0) {memcpy(&mEventCache[mCacheSize], scratch,remaningCacheSize * sizeof(sensors_event_t));}int numEventsDropped = count - remaningCacheSize;countFlushCompleteEventsLocked(mEventCache, numEventsDropped);// Drop the first "numEventsDropped" in the cache.memmove(mEventCache, &mEventCache[numEventsDropped],(mCacheSize - numEventsDropped) * sizeof(sensors_event_t));// Copy the remainingEvents in scratch buffer to the end of cache.memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,numEventsDropped * sizeof(sensors_event_t));}delete sanitizedBuffer;return status_t(NO_ERROR);}int index_wake_up_event = -1;if (mHasSensorAccess) {index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);if (index_wake_up_event >= 0) {scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;++mWakeLockRefCount;#if DEBUG_CONNECTIONS++mTotalAcksNeeded;#endif}}// NOTE: ASensorEvent and sensors_event_t are the same type.//重点在这边,把scratch里边的数据发出去,ssize_t size = SensorEventQueue::write(mChannel,reinterpret_cast<ASensorEvent const*>(scratch), count);if (size < 0) {// Write error, copy events to local cache.if (index_wake_up_event >= 0) {// If there was a wake_up sensor_event, reset the flag.scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;if (mWakeLockRefCount > 0) {--mWakeLockRefCount;}#if DEBUG_CONNECTIONS--mTotalAcksNeeded;#endif}if (mEventCache == NULL) {mMaxCacheSize = computeMaxCacheSizeLocked();mEventCache = new sensors_event_t[mMaxCacheSize];mCacheSize = 0;}memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));mCacheSize += count;// Add this file descriptor to the looper to get a callback when this fd is available for// writing.updateLooperRegistrationLocked(mService->getLooper());delete sanitizedBuffer;return size;}}
发现别无他法发送数据,唯有SensorEventQueue::write() 对复制得来的的scratch数据进行了处理,下面跳进该方法中:
ssize_t SensorEventQueue::write(const sp<BitTube>& tube,ASensorEvent const* events, size_t numEvents) {return BitTube::sendObjects(tube, events, numEvents);}
该方法仅仅调用了一下BitTube::sendObjects()方法,只能进入此方法中查看:
ssize_t BitTube::sendObjects(const sp<BitTube>& tube,void const* events, size_t count, size_t objSize){//SensorService::SensorEventConnection::mChannel::write()//mChannel 为 BitTube 对象const char* vaddr = reinterpret_cast<const char*>(events);ssize_t size = tube->write(vaddr, count*objSize);// should never happen because of SOCK_SEQPACKETLOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),"BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",count, objSize, size);
看到tube->write(),则继续跟进去看:
ssize_t BitTube::write(void const* vaddr, size_t size){ssize_t err, len;do {//这边通过 unix域套接字 发出去len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);// cannot return less than size, since we're using SOCK_SEQPACKETerr = len < 0 ? errno : 0;} while (err == EINTR);return err == 0 ? len : -err;}
这个send方法是 sys/socket.h中声明的,是Unix套接字,这里分析到发送端就结束了。
接下来分析接收端怎么接收的,应用是通过SensorManager注册一个SensorEventListener来接收数据的,主要是通过调用registerListener方法,代码如下:
public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs, Handler handler) {int delay = getDelay(samplingPeriodUs);return registerListenerImpl(listener, sensor, delay, handler, 0, 0);}
SystemSensorManager是SensorManager的实现类,其实现方法如下:
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {if (listener == null || sensor == null) {Log.e(TAG, "sensor or listener is null");return false;}// Trigger Sensors should use the requestTriggerSensor call.if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");return false;}if (maxBatchReportLatencyUs < 0 || delayUs < 0) {Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");return false;}if (mSensorListeners.size() >= MAX_LISTENER_COUNT) {throw new IllegalStateException("register failed, " +"the sensor listeners size has exceeded the maximum limit " +MAX_LISTENER_COUNT);}// Invariants to preserve:// - one Looper per SensorEventListener// - one Looper per SensorEventQueue// We map SensorEventListener to a SensorEventQueue, which holds the loopersynchronized (mSensorListeners) {SensorEventQueue queue = mSensorListeners.get(listener);if (queue == null) {Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;final String fullClassName = listener.getClass().getEnclosingClass() != null ?listener.getClass().getEnclosingClass().getName() :listener.getClass().getName();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);}}}
在各种合法性判断之后,先根据传入的listener获取对应的SensorEventQueue实例,如果不为空则调用addSensor方法,为空则创建该实例并调用addSensor方法最后将其加入mSensorListeners中,而创建实例时,会调用android/frameworks/base/core/jni/android_hardware_SensorManager.cpp nativeInitSensorEventQueue(),其源码如下:
static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);ScopedUtfChars packageUtf(env, packageName);String8 clientName(packageUtf.c_str());sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));if (queue == NULL) {jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");return 0;}sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);//获取MessageQueueif (messageQueue == NULL) {jniThrowRuntimeException(env, "MessageQueue is not initialized.");return 0;}sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);receiver->incStrong((void*)nativeInitSensorEventQueue);return jlong(receiver.get());}
这里创建了一个接收数据的Receiver对象,该类定义也在android_hardwate_SensorManager.cpp中,receiver又根据clientName创建了一个Native层的SensorEventQueue:
Receiver(const sp<SensorEventQueue>& sensorQueue,const sp<MessageQueue>& messageQueue,jobject receiverWeak) {JNIEnv* env = AndroidRuntime::getJNIEnv();//保存传进来的2个比较关键的对象引用mSensorQueue = sensorQueue;mMessageQueue = messageQueue;mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));}
receiver在执行incStrong时,会顺带执行它自己的onFirstRef()方法:
virtual void onFirstRef() {LooperCallback::onFirstRef();//获取套接字fdmMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,ALOOPER_EVENT_INPUT, this, mSensorQueue.get());}
上面将SensorEventQueue中BitTube里通过unix socket创建的mReceiveFd,添加到looper里,在Looper::pollInner()方法中通过epoll监听该fd,当有事件时,就会回调Receiver::hanldeEvent(),接下来看该方法:
virtual int handleEvent(int fd, int events, void* data) {JNIEnv* env = AndroidRuntime::getJNIEnv();sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));ssize_t n;ASensorEvent buffer[16];//这边最后是通过标准的socket接口recv将数据读取出来,代码在以下位置://android/frameworks/native/libs/sensor//SensorEventQueue::read() ==> BitTube::recvObjects()==>BitTube::read()while ((n = q->read(buffer, 16)) > 0) {for (int i=0 ; i<n ; i++) {if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {// step-counter returns a uint64, but the java API only deals with floatsfloat value = float(buffer[i].u64.step_counter);env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);} else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {float value[2];value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;value[1] = float(buffer[i].dynamic_sensor_meta.handle);env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);} else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {env->SetIntArrayRegion(mIntScratch, 0, 14,buffer[i].additional_info.data_int32);env->SetFloatArrayRegion(mFloatScratch, 0, 14,buffer[i].additional_info.data_float);} else {env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);}if (buffer[i].type == SENSOR_TYPE_META_DATA) {// This is a flush complete sensor event. Call dispatchFlushCompleteEvent// method.if (receiverObj.get()) {env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,buffer[i].meta_data.sensor);}} else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {// This is a flush complete sensor event. Call dispatchAdditionalInfoEvent// method.if (receiverObj.get()) {int type = buffer[i].additional_info.type;int serial = buffer[i].additional_info.serial;env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,buffer[i].sensor,type, serial,mFloatScratch,mIntScratch,buffer[i].timestamp);}}else {int8_t status;switch (buffer[i].type) {case SENSOR_TYPE_ORIENTATION:case SENSOR_TYPE_MAGNETIC_FIELD:case SENSOR_TYPE_ACCELEROMETER:case SENSOR_TYPE_GYROSCOPE:case SENSOR_TYPE_GRAVITY:case SENSOR_TYPE_LINEAR_ACCELERATION:status = buffer[i].vector.status;break;case SENSOR_TYPE_HEART_RATE:status = buffer[i].heart_rate.status;break;default:status = SENSOR_STATUS_ACCURACY_HIGH;break;}//关键就在这里,这边通过jni回调SystemSensorManager::dispatchSensorEvent(),将数据给SensorManagerif (receiverObj.get()) {env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchSensorEvent,buffer[i].sensor,mFloatScratch,status,buffer[i].timestamp);}}if (env->ExceptionCheck()) {mSensorQueue->sendAck(buffer, n);ALOGE("Exception dispatching input event.");return 1;}}//对SensorService::SensorEventConnection发送确认,//SensorService::SensorEventConnection::handleEvent()接收并确认mSensorQueue->sendAck(buffer, n);}if (n<0 && n != -EAGAIN) {// FIXME: error receiving events, what to do in this case?}return 1;}};
方法里面通过JNI 在C++代码里调用了SystemSensorManagre.java 中 BaseEventQueue的 dispatchSensorEvent(),下面为该方法(SensorEventQueue.java实现类)源码:
protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,long timestamp) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}SensorEvent t = null;synchronized (mSensorsEvents) {t = mSensorsEvents.get(handle);}if (t == null) {// This may happen if the client has unregistered and there are pending events in// the queue waiting to be delivered. Ignore.return;}// Copy from the values array.System.arraycopy(values, 0, t.values, 0, t.values.length);t.timestamp = timestamp;t.accuracy = inAccuracy;t.sensor = sensor;// call onAccuracyChanged() only if the value changesfinal 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(t);//在这边,通过多态回调应用开发者自己实现的onSensorChanged(),将sensor事件给到应用}
该方法最后调用了(SensorEventListener)listener的onSensorChanged方法,最后回调到了应用。
3.4总结
Sensor数据的分发最终还是走的Socket,SensorEventConnection类中持有 sp<BitTube>类型名为mChannel的实例,而其也持有一个应用包名字符串和Java虚拟机名字符串,一个应用对应一个SensorEventConnection,通过SensorEventConnection进行sensor监听的管理。
