android系统学习笔记十二

Android 的传感器系统

传感器的种类 

传感器名称

Java中的名称

 本地接口名称

数值

    加速度

TYPE_ACCELEROMETER

SENSOR_TYPE_ACCELEROMETER

1

磁场

TYPE_MAGNETIC_FIELD

SENSOR_TYPE_MAGNETIC_FIELD

2

方向

TYPE_ORIENTATION

SENSOR_TYPE_ORIENTATION

3

陀螺仪

TYPE_GYROSCOPE

SENSOR_TTYPE_GYROSCOPE

4

光线(亮度)

TYPE_LIGHT

SENSOR_TTYPE_LIGHT

5

压力

TYPE_PRESSURE

SENSOR_TTYPE_PRESSURE

6

温度

TYPE_TEMPERATURE

SENSOR_TTYPE_TEMPERATURE

7

接近

TYPE_PROXIMITY

SENSOR_TTYPE_PROXIMITY

8

重力传感

直线加速度

旋转矢量传感器

NFC(near  field  communication)近场通信

传感器的系统结构

传感器系统的java部分

 代码路径为:\frameworks\base\core\java\android\hardware

传感器系统的JNI部分

 代码路径为:\frameworks\base\core\jni\android_hardware_SensorManager.cpp

传感器系统的底层部分

  代码路径为:        \frameworks\base\include\gui

传感器的系统层次结构

   传感器系统的各个层次,自下而上为:

驱动程序

硬件抽象层

JNI

JAVA 

框架层对传感器器的应用

应用对传感器的应用

注本地部分已包含在JNI层中没有单独的实现库

传感器的JNI

  直接调用硬件抽象层,包含头文件 sensor.h头文件该 文件的路径为:ardware\libhardware\include\hardware

static JNINativeMethod gMethods[] = {

    {"nativeClassInit", "()V",              (void*)nativeClassInit },

    {"sensors_module_init","()I",           (void*)sensors_module_init },

    {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",

                                            (void*)sensors_module_get_next_sensor },

    {"sensors_create_queue",  "()I",        (void*)sensors_create_queue },

    {"sensors_destroy_queue", "(I)V",       (void*)sensors_destroy_queue },

    {"sensors_enable_sensor", "(ILjava/lang/String;II)Z",

                                            (void*)sensors_enable_sensor },

    {"sensors_data_poll",  "(I[F[I[J)I",     (void*)sensors_data_poll },

};

这些方法主要是供java层的sensorManager.java

static jint

sensors_module_init(JNIEnv *env, jclass clazz)

{

    SensorManager::getInstance();

    return 0;

}

调用hw_get_module()函数是硬件模块的通用接口,根据传感器硬件模块的标识SENSORS_HARDWARE_MODULE_ID打开这个硬件模块

传感器系统的java代码

 代码的路径为:\frameworks\base\core\java\android\hardware

sensorManager.java  传感器的核心管理类

Sensor.java  传感器的实体类

sensorEvent.java 传感器的事件类

(接口)

sensorEventListener.java 传感器事件的监听者

sensorListener.java  传感器的监听者 (不推荐使用)

sensorManager.java的几个主要方法:

public class SensorManager{

public Sensor getDefaultSensor(int type) { }  // 取得默认传感器

public List<Sensor> getSensorList(int type) {} //取默认传感器列表

以下两个方法使用sensorEventListener接口作为传感器的监听者

public boolean registerListener(SensorListener listener, int sensors) { }//注册传感器的监听者

 public void unregisterListener(SensorListener listener, int sensors) {}//注销注册监听

 在这个类中还定义了一些常量

public static final float GRAVITY_***  //重力常量

public static final float MAGNETIC_***磁场常量

public static final float LIGHT_***//亮度传感器

public class Sensor {

//以下是android 支持的十一种传感器类型

     public static final int TYPE_ACCELEROMETER = 1;

     public static final int TYPE_MAGNETIC_FIELD = 2;   

     public static final int TYPE_ORIENTATION = 3;

     public static final int TYPE_GYROSCOPE = 4;   

     public static final int TYPE_LIGHT = 5;

     public static final int TYPE_PRESSURE = 6;

     public static final int TYPE_TEMPERATURE = 7;      

     public static final int TYPE_PROXIMITY = 8;     

     public static final int TYPE_GRAVITY = 9;

     public static final int TYPE_LINEAR_ACCELERATION = 10;    

 public static final int TYPE_ROTATION_VECTOR = 11;  

//所有传感器类型

  public static final int TYPE_ALL = -1;

   

    private String  mName;   //名称

    private String  mVendor;  //

private int     mVersion;  //版本

    private int     mType;  //类型

private float   mMaxRange;  //取得传感器的最大范围

 private float   mResolution;// 传感器的解析度

private int     mHandle;   //

//以下是2.3版本中新添加

    private float   mPower;

    private int     mMinDelay;

    private int     mLegacyType;

}


//传感器监听

public interface SensorEventListener {  

    //数值发生变化时调用

    public void onSensorChanged(SensorEvent event);   

// 传感器精度发生变化时调用

    public void onAccuracyChanged(Sensor sensor, int accuracy);    

}

 传感器系统的硬件抽象层

 代码路径如下:\hardware\libhardware\include\hardware

Sensors.h头文件的部分路径如下:

//定义传感器类型

#define SENSOR_TYPE_ACCELEROMETER       1

#define SENSOR_TYPE_MAGNETIC_FIELD      2

#define SENSOR_TYPE_ORIENTATION         3

#define SENSOR_TYPE_GYROSCOPE           4

#define SENSOR_TYPE_LIGHT               5

#define SENSOR_TYPE_PRESSURE            6

#define SENSOR_TYPE_TEMPERATURE         7

#define SENSOR_TYPE_PROXIMITY           8

#define SENSOR_TYPE_GRAVITY             9

#define SENSOR_TYPE_LINEAR_ACCELERATION 10

#define SENSOR_TYPE_ROTATION_VECTOR     11

//hw_module_t common标准的硬件模块

struct sensors_module_t {

    struct hw_module_t common;

//获取传感器列表

     int (*get_sensors_list)(struct sensors_module_t* module,

            struct sensor_t const** list);

};

//传感器的描述性定义

struct sensor_t {

    const char*     name;    

    const char*     vendor;    

    int             version;   

    int             handle;   //传感器的句柄

    int             type;

    float           maxRange;

    float           resolution;

    float           power;    //能耗  ma

    int32_t         minDelay;  

    void*           reserved[8];

};

//表示传感器的数据

 union {

        float           data[16];

         sensors_vec_t   acceleration;  //方向

         sensors_vec_t   magnetic;    //磁矢量

         sensors_vec_t   orientation;  //加速度

         sensors_vec_t   gyro;        //陀螺仪

         float           temperature; //温度

         float           distance;    //距离

         float           light;       //亮度

         float           pressure;   //压强

    };

    uint32_t        reserved1[4];

} sensors_event_t;

//用户控制设备

struct sensors_poll_device_t {

    struct hw_device_t common;   

     int (*activate)(struct sensors_poll_device_t *dev,

            int handle, int enabled);

 

      int (*setDelay)(struct sensors_poll_device_t *dev,

            int handle, int64_t ns);

  

    

    int (*poll)(struct sensors_poll_device_t *dev,

            sensors_event_t* data, int count);

};

//用于打开和关闭传感器设备打开的过程从native_handle_t开始, pull函数是核心,

调用时被子阻塞,直到传感器获得数据返回

static inline int sensors_open(const struct hw_module_t* module,

        struct sensors_poll_device_t** device) {

    return module->methods->open(module,

            SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);

}

static inline int sensors_close(struct sensors_poll_device_t* device) {

    return device->common.close(&device->common);

}

   硬件抽象层的示例实现

模似器提供了一个示例实现,代码路径为:sdk\emulator\sensors

//

 static struct hw_module_methods_t sensors_module_methods = {

    .open = open_sensors

};

 open_sensors函数用于构建控制设备和数据设备

static int

open_sensors(const struct hw_module_t* module,

             const char*               name,

             struct hw_device_t*      *device)

{

    int  status = -EINVAL;

    D("%s: name=%s", __FUNCTION__, name);

    if (!strcmp(name, SENSORS_HARDWARE_CONTROL))

    {

        SensorControl *dev = malloc(sizeof(*dev));

        memset(dev, 0, sizeof(*dev));

        dev->device.common.tag       = HARDWARE_DEVICE_TAG;

        dev->device.common.version   = 0;

        dev->device.common.module    = (struct hw_module_t*) module;

        dev->device.common.close     = control__close;

        dev->device.open_data_source = control__open_data_source;

        dev->device.activate         = control__activate;

        dev->device.set_delay        = control__set_delay;

        dev->device.wake             = control__wake;

        dev->fd                      = -1;

        *device = &dev->device.common;

        status  = 0;

    }

    else if (!strcmp(name, SENSORS_HARDWARE_DATA)) {

        SensorData *dev = malloc(sizeof(*dev));

        memset(dev, 0, sizeof(*dev));

        dev->device.common.tag     = HARDWARE_DEVICE_TAG;

        dev->device.common.version = 0;

        dev->device.common.module  = (struct hw_module_t*) module;

        dev->device.common.close   = data__close;

        dev->device.data_open      = data__data_open;

        dev->device.data_close     = data__data_close;

        dev->device.poll           = data__poll;

        dev->events_fd             = -1;

        *device = &dev->device.common;

        status  = 0;

    }

    return status;

}

//定义取得传感器列表的函数指针

const struct sensors_module_t HAL_MODULE_INFO_SYM = {

    .common = {

        .tag = HARDWARE_MODULE_TAG,

        .version_major = 1,

        .version_minor = 0,

        .id = SENSORS_HARDWARE_MODULE_ID,

        .name = "Goldfish SENSORS Module",

        .author = "The Android Open Source Project",

        .methods = &sensors_module_methods,

    },

    .get_sensors_list = sensors__get_sensors_list

};

static uint32_t sensors__get_sensors_list(struct sensors_module_t* module,

        struct sensor_t const** list) 

{

    int  fd = qemud_channel_open(SENSORS_SERVICE_NAME);

    char buffer[12];

    int  mask, nn, count;

    int  ret;

    if (fd < 0) {

        E("%s: no qemud connection", __FUNCTION__);

        return 0;

    }

    ret = qemud_channel_send(fd, "list-sensors", -1);

    if (ret < 0) {

        E("%s: could not query sensor list: %s", __FUNCTION__,

          strerror(errno));

        close(fd);

        return 0;

    }

    ret = qemud_channel_recv(fd, buffer, sizeof buffer-1);

    if (ret < 0) {

        E("%s: could not receive sensor list: %s", __FUNCTION__,

          strerror(errno));

        close(fd);

        return 0;

    }

    buffer[ret] = 0;

    close(fd);

    /* the result is a integer used as a mask for available sensors */

    mask  = atoi(buffer);

    count = 0;

    for (nn = 0; nn < MAX_NUM_SENSORS; nn++) {

        if (((1 << nn) & mask) == 0)

            continue;

        sSensorList[count++] = sSensorListInit[nn];

    }

    D("%s: returned %d sensors (mask=%d)", __FUNCTION__, count, mask);

    *list = sSensorList;

    return count;

}

最后返回的是一个sensor_t类型的数组,部分代码如下(定义了四个传感器):

static const struct sensor_t sSensorListInit[] = {

         //加速度

        { .name       = "Goldfish 3-axis Accelerometer",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_ACCELERATION,

          .type       = SENSOR_TYPE_ACCELEROMETER,

          .maxRange   = 2.8f,

          .resolution = 1.0f/4032.0f,

          .power      = 3.0f,

          .reserved   = {}

        },

        //磁场

        { .name       = "Goldfish 3-axis Magnetic field sensor",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_MAGNETIC_FIELD,

          .type       = SENSOR_TYPE_MAGNETIC_FIELD,

          .maxRange   = 2000.0f,

          .resolution = 1.0f,

          .power      = 6.7f,

          .reserved   = {}

        },

         //方向

        { .name       = "Goldfish Orientation sensor",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_ORIENTATION,

          .type       = SENSOR_TYPE_ORIENTATION,

          .maxRange   = 360.0f,

          .resolution = 1.0f,

          .power      = 9.7f,

          .reserved   = {}

        },

        

        //温度

        { .name       = "Goldfish Temperature sensor",

          .vendor     = "The Android Open Source Project",

          .version    = 1,

          .handle     = ID_TEMPERATURE,

          .type       = SENSOR_TYPE_TEMPERATURE,

          .maxRange   = 80.0f,

          .resolution = 1.0f,

          .power      = 0.0f,

          .reserved   = {}

        },

};

static int

data__poll(struct sensors_data_device_t *dev, sensors_data_t* values)

{

    SensorData*  data = (void*)dev;

    int fd = data->events_fd;

    D("%s: data=%p", __FUNCTION__, dev);

    // there are pending sensors, returns them now...

    if (data->pendingSensors) {

        return pick_sensor(data, values);

    }

    // wait until we get a complete event for an enabled sensor

    uint32_t new_sensors = 0;

   //读取传感器信息 ,设置sensor_data_t结构体数据

    while (1) {

        /* read the next event */

        char     buff[256];

        int      len = qemud_channel_recv(data->events_fd, buff, sizeof buff-1);

        float    params[3];

        int64_t  event_time;

        if (len < 0) {

            E("%s: len=%d, errno=%d: %s", __FUNCTION__, len, errno, strerror(errno));

            return -errno;

        }

        buff[len] = 0;

        /* "wake" is sent from the emulator to exit this loop. This shall

         * really be because another thread called "control__wake" in this

         * process.

         */

        if (!strcmp((const char*)data, "wake")) {

            return 0x7FFFFFFF;

        }

        /* "acceleration:<x>:<y>:<z>" corresponds to an acceleration event */

        if (sscanf(buff, "acceleration:%g:%g:%g", params+0, params+1, params+2) == 3) {

            new_sensors |= SENSORS_ACCELERATION;

            data->sensors[ID_ACCELERATION].acceleration.x = params[0];

            data->sensors[ID_ACCELERATION].acceleration.y = params[1];

            data->sensors[ID_ACCELERATION].acceleration.z = params[2];

            continue;

        }

        /* "orientation:<azimuth>:<pitch>:<roll>" is sent when orientation changes */

        if (sscanf(buff, "orientation:%g:%g:%g", params+0, params+1, params+2) == 3) {

            new_sensors |= SENSORS_ORIENTATION;

            data->sensors[ID_ORIENTATION].orientation.azimuth = params[0];

            data->sensors[ID_ORIENTATION].orientation.pitch   = params[1];

            data->sensors[ID_ORIENTATION].orientation.roll    = params[2];

            continue;

        }

        /* "magnetic:<x>:<y>:<z>" is sent for the params of the magnetic field */

        if (sscanf(buff, "magnetic:%g:%g:%g", params+0, params+1, params+2) == 3) {

            new_sensors |= SENSORS_MAGNETIC_FIELD;

            data->sensors[ID_MAGNETIC_FIELD].magnetic.x = params[0];

            data->sensors[ID_MAGNETIC_FIELD].magnetic.y = params[1];

            data->sensors[ID_MAGNETIC_FIELD].magnetic.z = params[2];

            continue;

        }

        /* "temperature:<celsius>" */

        if (sscanf(buff, "temperature:%g", params+0) == 2) {

            new_sensors |= SENSORS_TEMPERATURE;

            data->sensors[ID_TEMPERATURE].temperature = params[0];

            continue;

        }

        /* "sync:<time>" is sent after a series of sensor events.

         * where 'time' is expressed in micro-seconds and corresponds

         * to the VM time when the real poll occured.

         */

        if (sscanf(buff, "sync:%lld", &event_time) == 1) {

            if (new_sensors) {

                data->pendingSensors = new_sensors;

                int64_t t = event_time * 1000LL;  /* convert to nano-seconds */

                /* use the time at the first sync: as the base for later

                 * time values */

                if (data->timeStart == 0) {

                    data->timeStart  = data__now_ns();

                    data->timeOffset = data->timeStart - t;

                }

                t += data->timeOffset;

                while (new_sensors) {

                    uint32_t i = 31 - __builtin_clz(new_sensors);

                    new_sensors &= ~(1<<i);

                    data->sensors[i].time = t;

                }

                return pick_sensor(data, values);

            } else {

                D("huh ? sync without any sensor data ?");

            }

            continue;

        }

        D("huh ? unsupported command");

    }

}

传感器硬件层实现的要点

可以支持多个传感器,也可支多个同类型的传感器,需要构建一个sensor_t类型的数组

传感器的控制设备和数据设备可能被扩展,用来保存传感器抽象层的上下文

  前提是sensor_control_device_tsensors_data_device_t两个数据结构需要作为扩展结构体的第一个成员

传感器在linux内核的驱动程序很可能使用misc驱动程序  这时需要在开发控制设备时,同样使用open          打开传感器的设备结点

传感器数据设备poll指针是实现的重点传感器在没有数据变化时实现阻塞,在数据变化时返回,

  根据驱动程序的情况可以使用poll,read 或者ioctl等接口来实现,这些驱动程序可以实现相应的阻塞

  当传感器控制设备的wake()被调用时,需要让数据设备的pool立即返回0x7fffffff

传感器的使用

 取得SensorManager(系统服务)

sensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);

OrientationEventListener扩展了sensorEventListener

 public OrientationEventListener(Context context, int rate) {

//取得传感器服务

 mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);

        mRate = rate;

        //取得加速度传感器

        mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

        if (mSensor != null) {

            // Create listener only if sensors do exist

            mSensorEventListener = new SensorEventListenerImpl();

        }

}

//注册传感器的监听事件

 public void enable() {

        if (mSensor == null) {

            Log.w(TAG"Cannot detect sensors. Not enabled");

            return;

        }

        if (mEnabled == false) {

            if (localLOGV) Log.d(TAG"OrientationEventListener enabled");

            mSensorManager.registerListener(mSensorEventListenermSensormRate);

            mEnabled = true;

        }

    }

    

 class SensorEventListenerImpl implements SensorEventListener {       

//通过加速度信信息取得方向信息

        public void onSensorChanged(SensorEvent event) {}

}

在清单文件中设置activity属性

android:screenOrientation="sensor"  //根据传感器设置屏幕方向

 如果属性设置为nosensor   则不会改变方向

你可能感兴趣的:(android系统学习笔记十二)