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(nearfieldcommunication)近场通信
传感器的系统结构
传感器系统的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
staticJNINativeMethodgMethods[]={
{"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
staticjint
sensors_module_init(JNIEnv*env,jclassclazz)
{
SensorManager::getInstance();
return0;
}
调用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的几个主要方法:
publicclassSensorManager{
publicSensorgetDefaultSensor(inttype){}//取得默认传感器
publicList<Sensor>getSensorList(inttype){}//取默认传感器列表
以下两个方法使用sensorEventListener接口作为传感器的监听者
publicbooleanregisterListener(SensorListenerlistener,intsensors){}//注册传感器的监听者
publicvoidunregisterListener(SensorListenerlistener,intsensors){}//注销注册监听
在这个类中还定义了一些常量
publicstaticfinalfloatGRAVITY_***//重力常量
publicstaticfinalfloatMAGNETIC_***磁场常量
publicstaticfinalfloatLIGHT_***//亮度传感器
publicclassSensor{
//以下是android支持的十一种传感器类型
publicstaticfinalintTYPE_ACCELEROMETER=1;
publicstaticfinalintTYPE_MAGNETIC_FIELD=2;
publicstaticfinalintTYPE_ORIENTATION=3;
publicstaticfinalintTYPE_GYROSCOPE=4;
publicstaticfinalintTYPE_LIGHT=5;
publicstaticfinalintTYPE_PRESSURE=6;
publicstaticfinalintTYPE_TEMPERATURE=7;
publicstaticfinalintTYPE_PROXIMITY=8;
publicstaticfinalintTYPE_GRAVITY=9;
publicstaticfinalintTYPE_LINEAR_ACCELERATION=10;
publicstaticfinalintTYPE_ROTATION_VECTOR=11;
//所有传感器类型
publicstaticfinalintTYPE_ALL=-1;
privateStringmName;//名称
privateStringmVendor;//
privateintmVersion;//版本
privateintmType;//类型
privatefloatmMaxRange;//取得传感器的最大范围
privatefloatmResolution;//传感器的解析度
privateintmHandle;//
//以下是2.3版本中新添加
privatefloatmPower;
privateintmMinDelay;
privateintmLegacyType;
}
//传感器监听
publicinterfaceSensorEventListener{
//数值发生变化时调用
publicvoidonSensorChanged(SensorEventevent);
//传感器精度发生变化时调用
publicvoidonAccuracyChanged(Sensorsensor,intaccuracy);
}
传感器系统的硬件抽象层
代码路径如下:\hardware\libhardware\include\hardware
Sensors.h头文件的部分路径如下:
//定义传感器类型
#defineSENSOR_TYPE_ACCELEROMETER1
#defineSENSOR_TYPE_MAGNETIC_FIELD2
#defineSENSOR_TYPE_ORIENTATION3
#defineSENSOR_TYPE_GYROSCOPE4
#defineSENSOR_TYPE_LIGHT5
#defineSENSOR_TYPE_PRESSURE6
#defineSENSOR_TYPE_TEMPERATURE7
#defineSENSOR_TYPE_PROXIMITY8
#defineSENSOR_TYPE_GRAVITY9
#defineSENSOR_TYPE_LINEAR_ACCELERATION10
#defineSENSOR_TYPE_ROTATION_VECTOR11
//在hw_module_tcommon标准的硬件模块
structsensors_module_t{
structhw_module_tcommon;
//获取传感器列表
int(*get_sensors_list)(structsensors_module_t*module,
structsensor_tconst**list);
};
//传感器的描述性定义
structsensor_t{
constchar*name;
constchar*vendor;
intversion;
inthandle;//传感器的句柄
inttype;
floatmaxRange;
floatresolution;
floatpower;//能耗ma
int32_tminDelay;
void*reserved[8];
};
//表示传感器的数据
union{
floatdata[16];
sensors_vec_tacceleration;//方向
sensors_vec_tmagnetic;//磁矢量
sensors_vec_torientation;//加速度
sensors_vec_tgyro;//陀螺仪
floattemperature;//温度
floatdistance;//距离
floatlight;//亮度
floatpressure;//压强
};
uint32_treserved1[4];
}sensors_event_t;
//用户控制设备
structsensors_poll_device_t{
structhw_device_tcommon;
int(*activate)(structsensors_poll_device_t*dev,
inthandle,intenabled);
int(*setDelay)(structsensors_poll_device_t*dev,
inthandle,int64_tns);
int(*poll)(structsensors_poll_device_t*dev,
sensors_event_t*data,intcount);
};
//用于打开和关闭传感器设备,打开的过程从native_handle_t开始,pull函数是核心,
调用时被子阻塞,直到传感器获得数据返回
staticinlineintsensors_open(conststructhw_module_t*module,
structsensors_poll_device_t**device){
returnmodule->methods->open(module,
SENSORS_HARDWARE_POLL,(structhw_device_t**)device);
}
staticinlineintsensors_close(structsensors_poll_device_t*device){
returndevice->common.close(&device->common);
}
硬件抽象层的示例实现
模似器提供了一个示例实现,代码路径为:sdk\emulator\sensors
//
staticstructhw_module_methods_tsensors_module_methods={
.open=open_sensors
};
open_sensors函数用于构建控制设备和数据设备
staticint
open_sensors(conststructhw_module_t*module,
constchar*name,
structhw_device_t**device)
{
intstatus=-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=(structhw_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;
}
elseif(!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=(structhw_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;
}
returnstatus;
}
//定义取得传感器列表的函数指针
conststructsensors_module_tHAL_MODULE_INFO_SYM={
.common={
.tag=HARDWARE_MODULE_TAG,
.version_major=1,
.version_minor=0,
.id=SENSORS_HARDWARE_MODULE_ID,
.name="GoldfishSENSORSModule",
.author="TheAndroidOpenSourceProject",
.methods=&sensors_module_methods,
},
.get_sensors_list=sensors__get_sensors_list
};
staticuint32_tsensors__get_sensors_list(structsensors_module_t*module,
structsensor_tconst**list)
{
intfd=qemud_channel_open(SENSORS_SERVICE_NAME);
charbuffer[12];
intmask,nn,count;
intret;
if(fd<0){
E("%s:noqemudconnection",__FUNCTION__);
return0;
}
ret=qemud_channel_send(fd,"list-sensors",-1);
if(ret<0){
E("%s:couldnotquerysensorlist:%s",__FUNCTION__,
strerror(errno));
close(fd);
return0;
}
ret=qemud_channel_recv(fd,buffer,sizeofbuffer-1);
if(ret<0){
E("%s:couldnotreceivesensorlist:%s",__FUNCTION__,
strerror(errno));
close(fd);
return0;
}
buffer[ret]=0;
close(fd);
/*theresultisaintegerusedasamaskforavailablesensors*/
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%dsensors(mask=%d)",__FUNCTION__,count,mask);
*list=sSensorList;
returncount;
}
最后返回的是一个sensor_t类型的数组,部分代码如下(定义了四个传感器):
staticconststructsensor_tsSensorListInit[]={
//加速度
{.name="Goldfish3-axisAccelerometer",
.vendor="TheAndroidOpenSourceProject",
.version=1,
.handle=ID_ACCELERATION,
.type=SENSOR_TYPE_ACCELEROMETER,
.maxRange=2.8f,
.resolution=1.0f/4032.0f,
.power=3.0f,
.reserved={}
},
//磁场
{.name="Goldfish3-axisMagneticfieldsensor",
.vendor="TheAndroidOpenSourceProject",
.version=1,
.handle=ID_MAGNETIC_FIELD,
.type=SENSOR_TYPE_MAGNETIC_FIELD,
.maxRange=2000.0f,
.resolution=1.0f,
.power=6.7f,
.reserved={}
},
//方向
{.name="GoldfishOrientationsensor",
.vendor="TheAndroidOpenSourceProject",
.version=1,
.handle=ID_ORIENTATION,
.type=SENSOR_TYPE_ORIENTATION,
.maxRange=360.0f,
.resolution=1.0f,
.power=9.7f,
.reserved={}
},
//温度
{.name="GoldfishTemperaturesensor",
.vendor="TheAndroidOpenSourceProject",
.version=1,
.handle=ID_TEMPERATURE,
.type=SENSOR_TYPE_TEMPERATURE,
.maxRange=80.0f,
.resolution=1.0f,
.power=0.0f,
.reserved={}
},
};
staticint
data__poll(structsensors_data_device_t*dev,sensors_data_t*values)
{
SensorData*data=(void*)dev;
intfd=data->events_fd;
D("%s:data=%p",__FUNCTION__,dev);
//therearependingsensors,returnsthemnow...
if(data->pendingSensors){
returnpick_sensor(data,values);
}
//waituntilwegetacompleteeventforanenabledsensor
uint32_tnew_sensors=0;
//读取传感器信息,设置sensor_data_t结构体数据
while(1){
/*readthenextevent*/
charbuff[256];
intlen=qemud_channel_recv(data->events_fd,buff,sizeofbuff-1);
floatparams[3];
int64_tevent_time;
if(len<0){
E("%s:len=%d,errno=%d:%s",__FUNCTION__,len,errno,strerror(errno));
return-errno;
}
buff[len]=0;
/*"wake"issentfromtheemulatortoexitthisloop.Thisshall
*reallybebecauseanotherthreadcalled"control__wake"inthis
*process.
*/
if(!strcmp((constchar*)data,"wake")){
return0x7FFFFFFF;
}
/*"acceleration:<x>:<y>:<z>"correspondstoanaccelerationevent*/
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>"issentwhenorientationchanges*/
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>"issentfortheparamsofthemagneticfield*/
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>"issentafteraseriesofsensorevents.
*where'time'isexpressedinmicro-secondsandcorresponds
*totheVMtimewhentherealpolloccured.
*/
if(sscanf(buff,"sync:%lld",&event_time)==1){
if(new_sensors){
data->pendingSensors=new_sensors;
int64_tt=event_time*1000LL;/*converttonano-seconds*/
/*usethetimeatthefirstsync:asthebaseforlater
*timevalues*/
if(data->timeStart==0){
data->timeStart=data__now_ns();
data->timeOffset=data->timeStart-t;
}
t+=data->timeOffset;
while(new_sensors){
uint32_ti=31-__builtin_clz(new_sensors);
new_sensors&=~(1<<i);
data->sensors[i].time=t;
}
returnpick_sensor(data,values);
}else{
D("huh?syncwithoutanysensordata?");
}
continue;
}
D("huh?unsupportedcommand");
}
}
传感器硬件层实现的要点
1可以支持多个传感器,也可支多个同类型的传感器,需要构建一个sensor_t类型的数组
2传感器的控制设备和数据设备可能被扩展,用来保存传感器抽象层的上下文
前提是sensor_control_device_t和sensors_data_device_t两个数据结构需要作为扩展结构体的第一个成员
3传感器在linux内核的驱动程序很可能使用misc驱动程序这时需要在开发控制设备时,同样使用open打开传感器的设备结点
4传感器数据设备poll指针是实现的重点,传感器在没有数据变化时实现阻塞,在数据变化时返回,
根据驱动程序的情况可以使用poll,read或者ioctl等接口来实现,这些驱动程序可以实现相应的阻塞
当传感器控制设备的wake()被调用时,需要让数据设备的pool立即返回0x7fffffff
传感器的使用
取得SensorManager(系统服务)
sensorManager=(SensorManager)this.getSystemService(Context.SENSOR_SERVICE);
OrientationEventListener扩展了sensorEventListener
publicOrientationEventListener(Contextcontext,intrate){
//取得传感器服务
mSensorManager=(SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
mRate=rate;
//取得加速度传感器
mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if(mSensor!=null){
//Createlisteneronlyifsensorsdoexist
mSensorEventListener=newSensorEventListenerImpl();
}
}
//注册传感器的监听事件
publicvoidenable(){
if(mSensor==null){
Log.w(TAG,"Cannotdetectsensors.Notenabled");
return;
}
if(mEnabled==false){
if(localLOGV)Log.d(TAG,"OrientationEventListenerenabled");
mSensorManager.registerListener(mSensorEventListener,mSensor,mRate);
mEnabled=true;
}
}
classSensorEventListenerImplimplementsSensorEventListener{
//通过加速度信信息取得方向信息
publicvoidonSensorChanged(SensorEventevent){}
}
在清单文件中设置activity属性
android:screenOrientation="sensor"//根据传感器设置屏幕方向
如果属性设置为nosensor则不会改变方向