`

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(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_tsensors_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则不会改变方向

分享到:
评论

相关推荐

    Android 系统相关学习笔记.zip

    Android 系统相关学习笔记.zip

    android系统模块之Contacts的学习笔记

    android系统模块之Contacts的学习笔记

    android开发学习笔记

    本人做android也有两年了,主要做智能机系统级开发,期间也承包了一些项目,对于如何学好android,以及学好android后如何开启自己的致富之门也能起到抛砖引玉的作用,欢迎大家加入,积极发言讨论,积极解决他人的...

    Android学习笔记.doc Android学习笔记.doc

    Android platform是一个用于开发移动程序的软件包,它包括了操作系统、中间件及一些关键应用。开发者能使用android SDK为Android platform开发应用,这些应用使用JAVA语言书写,运行在虚拟机Dalvik(一个专为手机程序...

    Pro Android学习:Menu

    是Pro Android学习笔记Menu系统的例子代码

    android入门学习笔记-永远不变的helloworld、初识activity

    本资源是上课时的笔记,系统的讲述了android。想学习andorid的新手可以载下来供参考使用

    Android知识系统总结+最佳学习线路图+实例+全程开发笔记

    Android知识系统总结+最佳学习线路图+实例+全程开发笔记Android知识系统总结+最佳学习线路图+实例+全程开发笔记

    Android学习笔记.doc

    Android platform是一个用于开发移动程序的软件包,它包括了操作系统、中间件及一些关键应用。开发者能使用android SDK为Android platform开发应用,这些应用使用JAVA语言书写,运行在虚拟机Dalvik(一个专为手机程序...

    android 系统笔记.zip

    操作系统:LInux、IOS、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络...

    android 学习笔记

    使用系统自带意图对象完成: Intent intent=new Intent(); intent.setAction("android.intent.action.Call"); intent.setData(Uri.parse("tel:"+i)); startActivity(Intent); 权限: &lt;uses-permission ...

    黑马程序员之android学习笔记--用户界面 View(一).docx

    黑马程序员之android学习笔记--用户界面 View(一).docx

    Android Map开发基础知识学习笔记

    本教程适用于Android Map学习的初学者,这是一本很平易近人的Android入门书籍,也是开发者及非开发者两相宜的实务书籍,它能陪伴你顺利入门,并驰骋于无限宽广的Android系统和应用领域

    Android知识系统总结

    里面包含7个常见android应用程序源代码,android学习笔记,开发入门实践,入门书籍等很有用的资料。

    第一行代码—Android第二版学习笔记

    Android 第一行代码学习笔记第一章 概述1.1安卓系统架构1.2Android四大组件1.3项目结构1.4app目录结构1.5 项目运行原理1.6 res目录详解1.7日志工具的使用第二章 活动2.1 创建基本活动2.2 使用Intent在活动之间跳转...

    Android学习笔记之——Content Providers

    之前博文《 Android学习笔记之——Android Studio的安装(3.6版本)、Java的基本语法及Android的概述 》曾经介绍过android有四大组件。本博文学习一下Content Providers(内容提供器) 目录 Android运行时 ...

    AOSP Android系统定制裁剪笔记.zip

    操作系统:LInux、IOS、树莓派、安卓开发、微机操作系统、网络操作系统、分布式操作系统等。此外,还有嵌入式操作系统、智能操作系统等。 网络与通信:数据传输、信号处理、网络协议、网络与通信硬件、网络安全网络...

    2021-学习相关-Android 局域网简易云端笔记系统源码.zip

    2021-学习相关-Android 局域网简易云端笔记系统源码.zip

    android移植到特定平台学习笔记

    android移植到Cortex-A8平台,手把手开发步骤,从安装编译器,配置环境变量,编译uboot,kernel,android文件系统详细步骤和修改的文件。最后是将镜像烧入SD卡等详细步骤!好东西不容错过

    Android代码-Android_Learning_Notes

    这是我的安卓学习笔记。 开始时间:2016-9-11 计划:一个半月 文章目录: 基础知识 1、Android01--搭建Android开发环境 2、Android02--认识Activity 3、Android03--Context和Application 4、Android04--Android服务 ...

Global site tag (gtag.js) - Google Analytics