Android Sensor流程

一.首先看一下sensor的整体架构:

 

 Android Sensor流程_第1张图片

 

第一层是应用层:代表上层使用frameworks的接口注册或使用一个sensor

Sensor sensor = sensorManager.getDefaultSensor(sensortype);
sensorManager.registerListener(mListener, sensor, SensorManager.SENSOR_DELAY_FASTEST);

第二层Frameworks层: 包含SensorService, 接收HAl层传上来的 sensor event 数据,并让应用层做出相应的动作,如陀螺仪转动,横竖屏切换等

第三层HAL层: kernel层的硬件驱动等, 有SensorDevice poll函数读取数据

  

二.分析SensorServier 的启动流程:

android系统中每一个功能点都是由Service来调度, 如熟知的ActivityManagerService, PackageManagerService等等, 这些我会在以后的博客中逐个分析

先看调用时序图

 

Android Sensor流程_第2张图片 

SystemServer中唯一的一个JNI调用启动SensorService

SystemServer.java :

/**
 * Start the sensor service.
 */
private static native void startSensorService();

 com_android_server_SystemServer.cpp:

void* sensorInit(void *arg) {
    ALOGI("System server: starting sensor init.\n");
    // Start the sensor service
    SensorService::instantiate();
    ALOGI("System server: sensor init done.\n");
    return NULL;
}

使用Binder机制将SensorService启动。

 SensorService的初始化:

Service的初始在SensorService::onFirstRef函数中

  SensorDevice& dev(SensorDevice::getInstance());  // 实例化SensorDevice
    if (dev.initCheck() == NO_ERROR) {
        sensor_t const* list;
        ssize_t count = dev.getSensorList(&list);   // 获取sensor list
        if (count > 0) {
            ssize_t orientationIndex = -1;
            bool hasGyro = false, hasAccel = false, hasMag = false;
            ... ... 
            mLastEventSeen.setCapacity(count);
            for (ssize_t i=0 ; irun("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
            run("SensorService", PRIORITY_URGENT_DISPLAY);
        }
}

SensorService的初始化主要有:

1. 创建SensorDevice实例,获取Sensor列表

2. 调用SensorDevice.getSensorList(),获取Sensor模块所有传感器列表并为为每个传感器注册监听器


SensorDevice的初始化:

SensorDevice::SensorDevice()
    :  mSensorDevice(0),
       mSensorModule(0)
{
    status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
            (hw_module_t const**)&mSensorModule);
    if (mSensorModule) {
        err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
         ... ...
        if (mSensorDevice) {
            if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||
                mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {
            }
 
            sensor_t const* list;
            ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
            mActivationCount.setCapacity(count);
            Info model;
            for (size_t i=0 ; iactivate( reinterpret_cast(mSensorDevice),list[i].handle, 0);
            ... ...
}

SensorService SensorDevice的启动主要实现一下几件事:

1. 调用HAL层的hw_get_modele()方法,加载Sensor模块so文件

2. 调用sensor.hsensors_open方法打开设备

3. 调用sensors_poll_device_t->activate()Sensor模块使能


启动一个线程,获取HAL层的数据:

SensorService::threadLoop():

bool SensorService::threadLoop()
{
    SensorDevice& device(SensorDevice::getInstance());
    const size_t vcount = mVirtualSensorList.size();
    const int halVersion = device.getHalDeviceVersion();
    do {
        ssize_t count = device.poll(mSensorEventBuffer, numEventMax);  // 从HAL层读取数据
        // Reset sensors_event_t.flags to zero for all events in the buffer.
        for (int i = 0; i < count; i++) {
             mSensorEventBuffer[i].flags = 0;
        }
        SortedVector< sp > activeConnections;
        populateActiveConnections(&activeConnections);
        ... ...
        // 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) {
                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);
                }
            }
        }
    ... ... 
    abort();
    return false;
}


进入while循环, 不停的从底层poll数据, 并sendEvent到上层

  

三. 客户端与服务端之间Sensor数据传递

先看服务器与客户端状态图:

Android Sensor流程_第3张图片


1. 上图涉及两个线程:

橘黄色服务端: SensorService::threadLoop 它通过SensorDevice::poll 不停的从HAL获取数据

蓝色客户端:android_hardware_SensorManager::Receiver EventQueue中读数据

 

2. 传递数据是的一个关键宏:sensors_event_t

    int32_t version;      // sensor 的version
    int32_t sensor;      //sensor 标识每个sensor都唯一
    int32_t type;        // sensor 的类型一个sensor可有多个类型 如: 陀螺仪有校准后与校准前类型
    int32_t reserved0; 
    int64_t timestamp;  // sensor产生时间戳
    union {
        union {
            float           data[16];
            sensors_vec_t   acceleration;    //加速sensor
            sensors_vec_t   magnetic;       // 磁场感应sensor
            sensors_vec_t   orientation;     // 横竖屏sensor
            sensors_vec_t   gyro;           // 陀螺仪sensor
            float           temperature;    //温度sensor
            float           distance;        // 距离sensor
            float           light;            // 光感sensor
            float           pressure;        //压力sensor
            float           relative_humidity; // 相对湿度sensor
            uncalibrated_event_t uncalibrated_gyro;      // 无定向的陀螺仪sensor
            uncalibrated_event_t uncalibrated_magnetic;  // 无定向的磁场sensor
 
            heart_rate_event_t heart_rate;  // 心率检测sensor
            meta_data_event_t meta_data;
        };
        union {
            uint64_t        data[8];
            uint64_t        step_counter; // 步数检测sensor
        } u64;
    };
    uint32_t flags;
    uint32_t reserved1[3];
} sensors_event_t;

4. 使用管道传递数据的原因是由于sensor数据量较大, Binder不能胜任此任务, 所以需要BitTube管道来传递这些数据

5. 数据时序图:


Android Sensor流程_第4张图片


根据图示可以看出客户端与服务端通过Binder建立链接, 通过BitTube管道进行数据传递。

BitTube init函数:

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // sine we don't use the "return channel", we keep it small...
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));  
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
        mReceiveFd = sockets[0];   //socket[0]接受数据
        mSendFd = sockets[1];     // socket[1]发送数据
    } else {
        mReceiveFd = -errno;
        ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
    }
}


    1. 使用socket[0] 来接收数据

2. 使用socket[1] 来发送数据

3.通过pipe(fds)创建管道,通过fcntl来设置操作管道的方式,设置通道两端的操作方式为O_NONBLOCK ,非阻塞IO方式,read或write调用返回-1和EAGAIN错误。


你可能感兴趣的:(Android源码分析)