美文网首页
Android Sensor Native 源码分析

Android Sensor Native 源码分析

作者: 安安_660c | 来源:发表于2022-11-23 15:36 被阅读0次

1.前言

本篇文档主要分析安卓 Sensor框架Native层如何实现SensorEvent的分发。下面是我分析的主要源码的路径:

2.传感器堆栈

下图显示了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

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++实现如下:
/*
* 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 },
};

//在这儿创建sensorservice
static 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实例并且添加到ServiceManage
        return 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 HAL
                bool 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 user
                registerSensor( 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线程用来不断检测是否需要持有wakelock
            mAckReceiver = 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 run
            enableSchedFifoMode();//降低主线程调度优先级
            // 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上报的数据就持有wakelock
        if (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报上来的数据的话,需要继续持有wakelock
        if (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交互。安卓系统开机时在
frameworks/base/core/java/android/app/SystemServiceRegistry.java中创建SystemSensorManger实例:

registerService(Context.SENSOR_SERVICE, SensorManager.class,
        new CachedServiceFetcher<SensorManager>() {
    @Override
    public 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 list
    for (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 jlong
nativeCreate
(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 construction
    assertStateLocked();
}

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件事情:

  1. 等待SensorService起来,获取到其指针
  2. 注册一个DeathObserver,当sensorManagerDied()时,做一些清理操作
  3. 获取sensorList里面的每一个sensor对象的地址

3.3 Sensor数据的分发

接下来分析SensorService如何将sensor数据分发到应用,上面SensorService启动时,我们知道SensorService启动了一个线程去执行threadLoop方法,这个方法首先调用SensorDevice::getInstance()方法,获取其实例引用,接下来就进入了一个调用SensorDevice::poll()方法的do while循环中,SensorDevice在其中扮演了十分重要的角色,主要通过该类从HAL层取数据,下面是SensorDevice的部分源码:

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-service
        mSensors = ISensors::getService();
        if (mSensors == nullptr) {
            // no sensor hidl service found
            break;
        }
        
        //.......
    }
    return (mSensors != nullptr);
}

与HAL层如何交互的分析已经远远超出我负责的范畴了,这里不做深入分析。我们只需知道Native层的Sensor数据是通过SensorDevice去HAL取得的就行了。当数据上来后,通过做一些判断和处理然后再分发给应用,其中判断处理包括:是否应该丢弃数据,是否是flush数据,是否需要将数据给融合sensor,应用是否已经关闭该sensor等,处理后,通过SensorService::SensorEventConnection::sendEvents将数据发出,senEvent()函数代码如下:

status_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 connection
 
    sensors_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的数据后,将要给到应用的数据拷到scratch
            do {
                // 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_CONNECTIONS
     mEventsReceived += count;
#endif
//将最新的数据缓存到mEventCache,后面可以dump出来debug
    if (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_SEQPACKET
    LOG_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_SEQPACKET
        err = 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 looper
        synchronized (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);//获取MessageQueue
    if (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();
    //获取套接字fd
    mMessageQueue->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 floats
                    float 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(),将数据给SensorManager
                    
                    
                    if (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 disconnected
                return;
            }
 
            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 changes
            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(t);//在这边,通过多态回调应用开发者自己实现的onSensorChanged(),将sensor事件给到应用
        }

该方法最后调用了(SensorEventListener)listener的onSensorChanged方法,最后回调到了应用。

3.4总结

Sensor数据的分发最终还是走的Socket,SensorEventConnection类中持有 sp<BitTube>类型名为mChannel的实例,而其也持有一个应用包名字符串和Java虚拟机名字符串,一个应用对应一个SensorEventConnection,通过SensorEventConnection进行sensor监听的管理。

来自:https://www.yuque.com/zestzone/bdds6v/viqstz

相关文章

网友评论

      本文标题:Android Sensor Native 源码分析

      本文链接:https://www.haomeiwen.com/subject/bjmzxdtx.html