sensorandroid
‘壹’ android sensor怎样注册input
一, 驱动层
在驱动层,内核需要增加和修改的部分包括:
1,相应硬件模块驱动代码,包括两个文件,这里是kionix_accel.h, kionix_accel.c,分别将kionix_accel.h放到kernel/common/customer/include/linux/中,将kionix_accel.c放到kernel/customer/drivers/misc/中;
2,编译目录(kernel/customer/drivers/misc/)下的Makefie 和KConfig,在KConfig中增加:
config SENSORS_KXTJ2
tristate "KXTJ2 accelerometer sensor driver"
depends on I2C
help
Say yes here to support Kionix's KXTJ2 accelerometer sensor
在MakeFile 下增加:obj-$(CONFIG_SENSORS_KXTJ2) += kionix_accel.o
3, 在平台编译配置文件中(也就是make menuconfig生成的),增加:CONFIG_SENSORS_KXTJ2=y------->指定编译到内核中,如果是m则编译成ko;
4,在平台模块代码文件中(kernel/customer/boards/board-m6g17-t069.c),在相应的i2c配置中,增加此模块:
static struct i2c_board_info __initdata aml_i2c_bus_info_b[] = {
........
#ifdef CONFIG_SENSORS_KXTJ2
{
I2C_BOARD_INFO("kionix_accel", KIONIX_ACCEL_I2C_ADDR),
//.irq = INT_GPIO_1,
.platform_data = (void *) &kionix_accel_pdata,
},
#endif
}
经过以上几步操作以后,就可以将此模块驱动编译到内核中。
G-sensor driver工作的大致流程:系统开机后,内核会先加载i2c总线驱动,然后再加载设备驱动,在设备驱动中的init函数中通过调用i2c_add_driver(&kionix_accel_driver)注册i2c_driver;此函数将driver注册到i2c_bus_type的总线上,此总线的匹配规则是利用i2c_client的名称和i2c_driver中id_table中的名称作匹配。其中i2c_client是系统自动创建的,board-m6g17-t069.c文件中的结构变量static struct i2c_board_info __initdata aml_i2c_bus_info_b中需要添加G-sensor的设备信息。
当匹配成功时,i2c_driver中的probe()函数开始执行。
mole_init(kionix_accel_init)---->i2c_add_driver(&kionix_accel_driver)----->static struct i2c_driver kionix_accel_driver = {
.driver = {
.name = KIONIX_ACCEL_NAME,
.owner = THIS_MODULE,
},
.probe = kionix_accel_probe,
.remove = __devexit_p(kionix_accel_remove),
.id_table = kionix_accel_id,
};
Probe()函数kionix_accel_probe()主要完成以下功能:
1.从i2c_client结构中得到初始化信息
2.创建G-sensor的工作队列
2.注册input_device设备
3.读取Chip ID
4.设置寄存器,使能G-sensor
5.设置并启动中断
当G-sensor上报数据的时候会触发中断,然后在中断处理函数中提交一个报值的任务到队列中并禁止中断。
在工作队列中读数G-sensor的数据并上报到input子系统中,最后使能中断。
系统启动后,驱动会在/sys/class/input/inputX下生成相应的设备文件,里面name节点包含有相应的模块名;
shell@
capabilities
device
event4
id
modalias
name
phys
power
properties
subsystem
uevent
uniq
同时会在/dev/input/里面也会生成inputX的节点,它是用来实际读取数据的。
驱动在工作的时候,主要分两部分:数据的采集及上报、设备的控制;
1,数据的采集主要是指通过I2C从硬件设备读取相关的数据并把数据上报,读取数据有两种方式,一种是通过中断,当有数据时,设备会发出中断信号给驱动,驱动去采集,另一种就是采用定时器不断的去定时采集数据;由于sensor也属于输入设备(还有TouchScreen,Keyboard,Mouse,Sensor等),所以上报的时候,也要报到linux kernel的输入子系统里面,上层通过相应的子系统设备节点读取数据。
上报数据的过程:static void report_abs(void)
{
short x,y,z,tilt;
if(read_data(&x,&y,&z,&tilt) != 0) {
/* report the absulate sensor data to input device */
input_report_abs(idev, ABS_X, y);
input_report_abs(idev, ABS_Y, x);
input_report_abs(idev, ABS_Z, z);
input_sync(idev);
}
2,设备的控制包括打开、关闭、设置参数和使能等,一般上层会通过ioctl方式来交互
二, HAL层
android的HAL层,相当于它的应用层中的驱动,HAL与内核硬件驱动密切相关,由于硬件模块的差别性,HAL代码的编写也各有差别,特别是关于sensor的HAL代码基本上都要自己去实现,但基本架构是一样的。
sensor的HAL结构基本分两部分,一部分是控制操作,一部分是数据操作;
1,首先在android\hardware\libhardware\include\hardware目录下,有sensors.h文件,定义了struct sensors_mole_t(sensor模块对象结构,如get_list), struct sensor_t(具体sensor设备对象结构,如名字,类型), struct sensors_poll_device_t(每个设备操作数据结构,如激活、设置参数、poll等), typedef struct sensors_event_t(sensor的事件结构,如类型、数据), 同时也定义了所有传感器的类型:
/**
* Sensor types
*/
#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 // deprecated
#define SENSOR_TYPE_PROXIMITY 8
#define SENSOR_TYPE_GRAVITY 9
#define SENSOR_TYPE_LINEAR_ACCELERATION 10
#define SENSOR_TYPE_ROTATION_VECTOR 11
#define SENSOR_TYPE_RELATIVE_HUMIDITY 12
#define SENSOR_TYPE_AMBIENT_TEMPERATURE 13
在android/hardware/amlogic/sendsors/aml_gsensor目录是特定平台实际HAL的代码存放的位置,当然也有的平台只会给一个so的文件,不给源码。
在sensor_aml.cpp中,首先要定义HAL_MODULE_INFO_SYM,这个是每个HAL模块必须的,
struct sensors_mole_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: SENSORS_HARDWARE_MODULE_ID,
name: "Sensors mole",
author: "Amlogic",
methods: &sensors_mole_methods,
},
get_sensors_list: sensors__get_sensors_list,
};
static int sensors__get_sensors_list(struct sensors_mole_t* mole,
struct sensor_t const** list)
{
*list = sSensorList;
return ARRAY_SIZE(sSensorList);
}
/* The SENSORS Mole */
static const struct sensor_t sSensorList[] = {
{ "BMA250 3-axis Accelerometer",
"Bosch",
1, SENSORS_ACCELERATION_HANDLE,
SENSOR_TYPE_ACCELEROMETER,
4.0f*9.81f,
(4.0f*9.81f)/1024.0f,
0.2f,
0,
{ }
},
#ifdef ENABLE_LIGHT_SENSOR
{ "Light sensor",
"(none)",
1, SENSORS_LIGHT_HANDLE,
SENSOR_TYPE_LIGHT, 5000.0f, 1.0f, 1.0f, 20000,{ } },
#endif
};
可以看出在事先定义当前支持的sensor模块,android通过mole->get_sensors_list获取。
获取mole后,利用open_sensors();得到hw_device_t ==sensors_poll_device_t==sensors_poll_context_t->device mSensor结构对象,这个结构对象在初始化时会创建相应的sensor对象,且它们都是以SensorBase为基础类,
sensors_poll_context_t::sensors_poll_context_t()
{
mSensors[aml_accel] = new GSensor();
mPollFds[aml_accel].fd = mSensors[aml_accel]->getFd();
mPollFds[aml_accel].events = POLLIN;
mPollFds[aml_accel].revents = 0;
#ifdef ENABLE_LIGHT_SENSOR
mSensors[aml_light] = new LightSensor();
mPollFds[aml_light].fd = mSensors[aml_light]->getFd();
mPollFds[aml_light].events = POLLIN;
mPollFds[aml_light].revents = 0;
#endif
}
通过mSensor对象就可以调用 activate、setDelay、poll进行激活读取数据处理了。
mSensors[aml_accel] = new GSensor();
在创建GSensor对象时会对/sys/class/input/inputX目录下的name读取,通过对比名称判断当前sensor到底是在哪个目录并记录下path,在后面对设备进行设置,也就是控制部分会用到这个目录下的结点;
同时由于GSensor 是继承sensorBase的,所以在构造sendsorBase的时候会找到相应的/dev下的inputX设备open得到设备fd,用于后面读取数据,也就是数据部分。
HAL层准备好后,最后会编译成一个库,这里为sensor.amlogic.so
三, Framework层
对于每一个模块,framework层是最复杂的,它涉及到java部分和C++部分,且根据功能,又可分为service部分和manager部分,它们之间是通过binder进行通信的。
frameworks/base/libs/gui/ISensorServer.cpp
class ISensorServer : public IInterface
{
public:
DECLARE_META_INTERFACE(SensorServer);
virtual Vector<Sensor> getSensorList() = 0;
virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;
};
在Android中,和Sensor相关的几个类是:
SensorManager : 通过它实现系统对Sensor的相关调用。
SensorEvent :对各个Sensor数据的封装,具体可以参考Android的开发文档。
SensorEventListener :对Sensor数据的监视,一旦有数据,就会调相应的函数。
Sensor : 对Sensor的封装。
对于service部分: 它是负责与HAL层建立联系并处理实际数据的服务。
frameworks/base/services/sensorservice/sensorService.cpp , 它继承了public BnSensorServer
系统启动时会执行systemProcess,同时会加载sensorService.java进程,在sensorService.java的构造函数中调用JNI方法_sensor_control_init()。
sensorService.cpp中SensorService::onFirstRef()会被执行,会创建SensorDevice& dev(SensorDevice::getInstance())对象,通过SensorService::threadLoop()里就对各个sensor进行poll并将数据发送到对应的申请connection中connection->sendEvents(buffer, count, scratch);
SensorDevice是一个单一对象类,故SensorDevice::getInstance()会在同一进程中只保留一个对象,SensorDevice::SensorDevice()通过hardware.c中读取HAL层生成的sensor.amlogic.so库。
对于manager部分:它是负责给应用程序提供接口的,与sensorserivce通过binder进行交互数据与控制。
frameworks/base/core/java/android/hardware/SensorManager.java
frameworks/base/core/jni/android_hardware_SensorManager.cpp
frameworks/base/libs/gui/sensorManager.cpp
android_hardware_SensorManager.cpp:
static JNINativeMethod gMethods[] = {
{"nativeClassInit", "()V", (void*)nativeClassInit },
{"sensors_mole_init","()I", (void*)sensors_mole_init },
{"sensors_mole_get_next_sensor","(Landroid/hardware/Sensor;I)I", (void*)sensors_mole_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 },
};
sensors_mole_init()---->SensorManager::getInstance();由于SensorManager也是单一对象类,这里生成实体对象;
sensors_create_queue()----->SensorManager& mgr.createEventQueue():
sp<SensorEventQueue> SensorManager::createEventQueue()
{
sp<SensorEventQueue> queue;
Mutex::Autolock _l(mLock);
while (assertStateLocked() == NO_ERROR) {
sp<ISensorEventConnection> connection =
mSensorServer->createSensorEventConnection();
if (connection == NULL) {
// SensorService just died.
LOGE("createEventQueue: connection is NULL. SensorService died.");
continue;
}
queue = new SensorEventQueue(connection);
break;
}
return queue;
}
通过创建一个connection来建立queuece,其实就是利用connection中与sensorService建立的channel:
mSensorChannel = mSensorEventConnection->getSensorChannel();
通过循环获取sensor list中的各个对象的属性:
sensors_mole_get_next_sensor()------>sensorManager::getSensorList()----->SensorManager::assertStateLocked()---->mSensorServer->getSensorList()通过binder从sensorService获取sensorlist;
使能某一sensor对象:
sensors_enable_sensor()---->queue->enableSensor(sensor, delay)---->mSensorEventConnection->setEventRate(handle, us2ns(us))-----> 通过ISensorEventConnection对象与sensorService:SensorEventConnection进行交互-------->SensorService::SensorEventConnection::enableDisable(int handle, bool enabled)---> SensorService::enable()---->mActiveConnections.add(connection)只是将connection加入到激活数组中,而并非直接使能或关闭硬件;
循环监听事件:
sensorChannel用一对pipe来sensorService到sensorEventQueue的事件信息。
sensors_data_poll()------->queue->read(&event, 1)---->mSensorChannel->read()----->通过pipe<------ SensorChannel::write()<---------mChannel->write() <----------SensorService::SensorEventConnection::sendEvents() <-------activeConnections[i]->sendEvents(buffer, count, scratch)<---------SensorService::threadLoop()
四, 应用层
‘贰’ android如何实现陀螺仪 sensor 在 android 吗
千锋扣丁学堂Android开发为您解答:
sensors.h中还定义了其他各种sensor。要实现的就是这两个:
#define SENSOR_TYPE_MAGNETIC_FIELD 2
#define SENSOR_TYPE_ORIENTATION 3
在/hardware/sensors/sensors.cpp 中添加对MAGNETIC_FIELD和ORIENTATION 的支持
[cpp] view plain
//加入需要的宏定义
#define ID_BASE SENSORS_HANDLE_BASE
#define ID_ACCELERATION (ID_BASE+0)
#define ID_MAGNETIC_FIELD (ID_BASE+1)
#define ID_ORIENTATION (ID_BASE+2)
#define S_HANDLE_ACCELEROMETER (1<<ID_ACCELERATION)
#define S_HANDLE_MAGNETIC_FIELD (1<<ID_MAGNETIC_FIELD)
#define S_HANDLE_ORIENTATION (1<<ID_ORIENTATION)
#define SENSORS_NUM 4
#define SUPPORTED_SENSORS ((1<<NUM_SENSORS)-1)
//在 sensor_t sensors_list[] 中添加两个sensor的信息,
//这些只是一些Sensor的信息,应用程序可以获取到。
#ifdef MAGNETIC_FIELD
{
name : "XXX 3-axis Magnetic field sensor",
vendor : "XXX company",
version : 1,
handle : S_HANDLE_MAGNETIC_FIELD,
type : SENSOR_TYPE_MAGNETIC_FIELD,
maxRange : 600.0f,//最大范围
resolution : 30.0f,//最小分辨率
power : 6.7f,//这个不太懂
},
#endif
#ifdef ORIENTATION
{
name: "XXX Orientation sensor",
vendor: "XXX company",
version: 1,
handle: S_HANDLE_ORIENTATION,
type: SENSOR_TYPE_ORIENTATION,
maxRange: 360,
resolution: 0.1,
power: 20,
},
#endif
//定义一个结构来保存orientation的信息
static struct orientation{
float azimuth;
float pitch;
float roll;
}orientation;
//在 control__open_data_source()函数中打开设备
static native_handle_t*
control__open_data_source(struct sensors_control_device_t *dev)
{
SensorControl* ctl = (void*)dev;
native_handle_t* handle;
int fd_m = open (MAGNETIC_DATA_DEVICE, O_RDONLY);
LOGD ("Open Magnetic Data source: %d, %d/n", fd_m, errno);
if (fd_m>= 0)
{
dev->fd[ID_MAGNETIC_FIELD] = p(fd_m);
}
return handle;
}
//实现数据的打开和关闭函数
static int
data__data_open(struct sensors_data_device_t *dev, native_handle_t* handle)
{
struct sensors_data_context_t *dev;
dev = (struct sensors_data_context_t *)device;
for(int i=0 ;i<SENSORS_NUM; i++)
{
dev->fd[i] = p(handle->data[i]);
}
native_handle_close(handle);
native_handle_delete(handle);
return 0;
}
static int
data__data_close(struct sensors_data_device_t *dev)
{
struct sensors_data_context_t *dev;
dev = (struct sensors_data_context_t *)device;
for(int i=0 ;i<SENSORS_NUM; i++)
{
if (dev->fd[i] >= 0)
{
close(dev->fd[i]);
}
dev->fd[i] = -1;
}
return 0;
}
//最关键的poll函数
static int
data__poll(struct sensors_data_device_t *dev, sensors_data_t* values)
{
SensorData* data = (void*)dev;
int fd = data->events_fd;
//判断设备是否打开
if(dev->fd[ID_MAGNETIC_FIELD] < 0)
{
LOGD("In %s dev[%d] is not open!/n",__FUNCTION__ ,ID_MAGNETIC_FIELD);
return -1;
}
pollfd pfd[SENSORS_NUM] =
{
//省略其他sensor代码
{
fd: dev->fd[ID_MAGNETIC_FIELD],
events: POLLIN,
revents: 0
},
//省略其他sensor代码
};
int err = poll (pfd, SENSORS_NUM, s_timeout);
unsigned int mask = SUPPORTED_SENSORS;
static unsigned int poll_flag=0;
if(poll_flag==0)
{
poll_flag = mask;
}
//省略其他sensor
if(poll_flag&(1<<ID_MAGNETIC_FIELD))
{
if((pfd[ID_MAGNETIC_FIELD].revents&POLLIN) == POLLIN)
{
char rawData[6];
err = read (dev->fd[ID_MAGNETIC_FIELD], &rawData, sizeof(rawData));
if(err<0)
{
LOGE("read magnetic field ret:%d errno:%d/n", err, errno);
return err;
}
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
data->time = timespec_to_ns(&t);
data->sensor = SENSOR_TYPE_MAGNETIC_FIELD;
data->magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
//上报的数据单位要转换成 uTesla
data->magnetic.x = ( (rawData[1] << 8 ) | rawData[0])/ MAGNETIC_CONVERT;
data->magnetic.y = ( (rawData[3] << 8 ) | rawData[2])/ MAGNETIC_CONVERT;
data->magnetic.z = ( (rawData[5] << 8 ) | rawData[4])/ MAGNETIC_CONVERT;
//把陀螺仪需要的数据计算出来,用atan2(),头文件要加上#include <math.h>
float azimuth = atan2( (float)(data->magnetic.x ),(float)(data->magnetic.y) );
if(azimuth<0)
{
azimuth = 360 - fabs(azimuth*180/PI);
}
else
{
azimuth = azimuth*180/PI;
}
orientation.azimuth = 360-azimuth;
//rotation around the X axis.+180~-180 degree
orientation.pitch = atan2( (float)(data->magnetic.y ),(float)(data->magnetic.z)
)*180/PI;
//rotation around the Y axis +90~-90 degree
float roll = atan2( (float)(data->magnetic.x ),(float)(data->magnetic.z) )
*180/PI;
if (roll > 90)
{
roll = -(180.0-roll);
}
else if (roll < -90)
{
roll = 180 + roll;
}
orientation.roll = roll;
}
return S_HANDLE_MAGNETIC_FIELD;
}
if(poll_flag&(1<<ID_MAGNETIC_FIELD))
{
//数据已经计算好了直接上报就行
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
data->time = timespec_to_ns(&t);
data->sensor = SENSOR_TYPE_ORIENTATION;
data->orientation.azimuth = orientation.azimuth;
data->orientation.pitch = orientation.pitch;
data->orientation.roll = orientation.roll;
poll_flag &= ~(1<<ID_ORIENTATION);
return S_HANDLE_ORIENTATION;
}
}
‘叁’ android sensor信息能不能hook
首先我们可以用Xposed框架来hook计数传感器的队列函数dispatchSensorEvent(),这个函数在android.hardware.SystemSensorManager$SensorEventQueue这个类中。随后在微信运动每次询问行走步数的时候,我们先获取当前步数,然后在目前的步数的基础上加1000步,然后将信息返回给微信运动。微信运动就会误以为我们运动了1000步,从而达到了欺骗的效果。
关键代码如下:
首先hook android.hardware.SystemSensorManager$SensorEventQueue这个类的dispatchSensorEvent()函数:
final Class<?> sensorEL = findClass("android.hardware.SystemSensorManager$SensorEventQueue",lpparam.classLoader);
XposedBridge.hookAllMethods(sensorEL, "dispatchSensorEvent", new XC_MethodHook()
接着我们在记步传感器把步数信息返回给微信运动之前,将返回的步数加上1000步:
protected void beforeHookedMethod(MethodHookParam param) throws
Throwable {
XposedBridge.log(" mzheng Hooked method: " + param.method);
((float[]) param.args[1])[0]=((float[]) param.args[1])[0]+1000*WechatStepCount;
WechatStepCount+=1;
…
另外我们还可以使用一些传感器的接口获取一些数据的信息:
Sensor ss = ((SparseArray<Sensor>) field.get(0)).get(handle);
XposedBridge.log(" SensorEvent: sensor=" + ss);
比如说x就代表开机以来行走的步数,timestamp是获取步数时候的时间戳等。
另外,我们不仅在android上可以hook计步器,在iOS上也是可以通过越狱后hook iHealth的API接口达到同样的作弊效果,有兴趣的同学可以继续研究。
‘肆’ android如何实现陀螺仪 sensor 在 android 吗
设备中的三自由度Orientation
Sensor就是一个可以识别设备相对于地面,绕x、y、z轴转动角度的感应器(自己的理解,不够严谨)。智能手机,平板电脑有了它,可以实现很多好玩的应用,比如说指南针等。
我们可以用一个磁场感应器(magnetic sensor)来实现。
磁场感应器是用来测量磁场感应强度的。一个3轴的磁sensor
IC可以得到当前环境下X、Y和Z方向上的磁场感应强度,对于Android中间层来说就是读取该感应器测量到的这3个值。当需要时,上报给上层应用程序。磁感应强度的单位是T(特斯拉)或者是Gs(高斯),1T等于10000Gs。
先来看看android定义的坐标系,在/hardware/libhardware/include/hardware/sensors.h中有个图。
求z和x的反正切可得到此值。
sensors.h中还定义了其他各种sensor。要实现的就是这两个:
#define SENSOR_TYPE_MAGNETIC_FIELD 2
#define SENSOR_TYPE_ORIENTATION 3
在/hardware/sensors/sensors.cpp 中添加对MAGNETIC_FIELD和ORIENTATION 的支持
‘伍’ 什么叫 sensor android
sensor android 就是安卓的传感器,例如:重力感应、陀螺仪
Sensor作为Android系统的一个输入设备,对Android设备来说是必不可少的。Sensor主要包括G-Sensor、LightsSensor、ProximitySensor、TemperatureSensor等。这里主要对G-Sensor模块进行解析。
希望能帮到你
‘陆’ android sensor怎样创建设备节点
在Android中,由于没有mdev和udev,所以它没有办法动态的生成设备节点,那么它是如何做的呢?
我们可以在system/core/init/下的init.c和devices.c中找到答案:
init.c中
在Android中,没有独立的类似于udev或者mdev的用户程序,这个功能集成到了init中做了。代码见:system/core/init/init.c文件,如下:
if (ufds[0].revents == POLLIN)
handle_device_fd(device_fd);
其中handle_device_fd(device_fd)函数在system/core/init/devices.c中实现,参数device_fd 由函数device_init()->open_uevent_socket()->socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)函数调用返回。
函数handle_device_fd(device_fd)中,根据传进来的device_fd参数,调用recv(fd, msg, UEVENT_MSG_LEN, 0)函数,将内核探测到的设备并通过NETLINK机制传过来的socket描述符转化成消息。接着调用parse_event(msg, &uevent);函数将消息翻译成uevent事件,并将改事件传递给handle_device_event(&uevent)函数。
handle_device_event(&uevent)函数中,依据参数uevent->subsystem类型创建dev下的相应目录,如:/dev/graphics。紧接着根据uevent->action是"add"还是"remove"来实现设备节点的创建与删除。如果uevent->action是"add",则调用make_device(devpath, block, uevent->major, uevent->minor)函数生成设备节点。如果uevent->action是"remove",则调用unlink(devpath)对设备节点进行删除。
‘柒’ android手机都有哪些sensor
1.Sensor Type
重力感应/加速度传感器 (G-Sensor)
光感应 (Light-Sensor)
温度感应
方向感应
磁场、
临近性
2.如何实现Sensor编程
a.获取系统服务(SENSOR_SERVICE)返回一个SensorManager 对象
sensormanager = (SensorManager)getSystemSeriver(SENSOR_SERVICE);
b.通过SensorManager对象获取相应的Sensor类型的对象
sensorObject = sensormanager.getDefaultSensor(sensor Type);
c.声明一个SensorEventListener 对象用于侦听Sensor 事件,并重载onSensorChanged方法
SensorEventListener sensorListener = new SensorEventListener(){
};
d.注册相应的SensorService
sensormanager.registerListener(sensorListener, sensorObject, Sensor TYPE);
e.销毁相应的SensorService
sensormanager.unregisterListener(sensorListener, sensorObject);
f: SensorListener 接口是传感器应用程序的中心。它包括两个必需方法:
onSensorChanged(int sensor,float values[]) 方法在传感器值更改时调用。
该方法只对受此应用程序监视的传感器调用(更多内容见下文)。该方法的参数包括:一个整数,指示更改的传感器;一个浮点值数组,表示传感器数据本身。有些传感器只提供一个数据值,另一些则提供三个浮点值。方向和加速表传感器都提供三个数据值。
当传感器的准确性更改时,将调用 onAccuracyChanged(int sensor,int accuracy) 方法。参数包括两个整数:一个表示传感器,另一个表示该传感器新的准确值。
3.关于G-Sensor
Android 加速度传感器的类型是 Sensor.TYPE_ACCELEROMETER
通过 android.hardware.SensorEvent 返回加速度传感器值。
加速度传感器返回值的单位是加速度的单位 m/s^2(米每二次方秒),有三个方向的值分别是
values[0]: x-axis 方向加速度
values[1]: y-axis 方向加速度
values[2]: z-axis 方向加速度
其中x,y,z方向的定义是以水平放置在的手机的右下脚为参照系坐标原点
x 方向就是手机的水平方向,右为正
y 方向就是手机的水平垂直方向,前为正
y 方向就是手机的空间垂直方向,天空的方向为正,地球的方向为负
需要注意的是,由于地球固有的重力加速度g (值为9.8 m/s^2),
因此现实中实际加速度值应该是 z方向返回值 - 9.8 m/s^2.
比如你以 2 m/s^2 的加速度将手机抛起,这时z方向的返回值应该是 11.8 m/s^2.
反之若以手机以2 m/s^2 的加速度坠落,则z方向的返回值应该是 7.8 m/s^2.
x,y方向则没有上述限制。
‘捌’ 在android上面 如何 通过sensor来获取手机当前的运动方向
不知道是不是你想要的。
package com.yarin.android.Examples_09_01;
import java.util.List;
import android.app.Activity;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
public class Activity01 extends Activity implements SensorEventListener
{
private boolean mRegisteredSensor;
//定义SensorManager
private SensorManager mSensorManager;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mRegisteredSensor = false;
//取得SensorManager实例
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
@Override
protected void onResume()
{
super.onResume();
//接受SensorManager的一个列表(Listener)
//这里我们指定类型为TYPE_ORIENTATION(方向感应器)
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
if (sensors.size() > 0)
{
Sensor sensor = sensors.get(0);
//注册SensorManager
//this->接收sensor的实例
//接收传感器类型的列表
//接受的频率
mRegisteredSensor = mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
}
}
@Override
protected void onPause()
{
if (mRegisteredSensor)
{
//如果调用了registerListener
//这里我们需要unregisterListener来卸载\取消注册
mSensorManager.unregisterListener(this);
mRegisteredSensor = false;
}
super.onPause();
}
//当进准度发生改变时
//sensor->传感器
//accuracy->精准度
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
// 当传感器在被改变时触发
@Override
public void onSensorChanged(SensorEvent event)
{
// 接受方向感应器的类型
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION)
{
//这里我们可以得到数据,然后根据需要来处理
//由于模拟器上面无法测试效果,因此我们暂时不处理数据
float x = event.values[SensorManager.DATA_X];
float y = event.values[SensorManager.DATA_Y];
float z = event.values[SensorManager.DATA_Z];
}
}
}
‘玖’ android 非上层程序怎么调用sensor
Android上层应用apk到G-sensor driver的大致流程: Android HAL层,即硬件抽象层,是Google响应厂家“希望不公开源码”的要求推出的新概念 1,源代码和目标位置 源代码: /hardware/libhardware目录,该目录的目录结构如下: /hardware/libhardware/hardware.c编译成libhardware.so,目标位置为/system/lib目录 /hardware/libhardware/include/hardware目录下包含如下头文件: hardware.h 通用硬件模块头文件 bit.h bit模块头文件 gralloc.h gralloc模块头文件 qemud.h qemud模块头文件 sensors.h 传感器模块头文件 /hardware/libhardware/moles目录下定义了很多硬件模块 这些硬件模块都编译成xxx.xxx.so,目标位置为/system/lib/hw目录 2,Android对于Sensor的API定义在 hardware/libhardware/include/hardware/sensor.h中,要求在sensor.so提供以下8个API函数 [控制方面] int (*open_data_source)(struct sensors_control_device_t *dev); int (*activate)(struct sensors_control_device_t *dev, int handle, int enabled); int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms); int (*wake)(struct sensors_control_device_t *dev); [数据方面] int (*data_open)(struct sensors_data_device_t *dev, int fd); int (*data_close)(struct sensors_data_device_t *dev); int (*poll)(struct sensors_data_device_t *dev, sensors_data_t* data); [模块方面] int (*get_sensors_list)(struct sensors_mole_t* mole, struct sensor_t const** list); 在Java层Sensor的状态控制由SensorService来负责,它的java代码和JNI代码分别位于: frameworks/base/services/java/com/Android/server/SensorService.java frameworks/base/services/jni/com_Android_server_SensorService.cpp 在Java层Sensor的数据控制由SensorManager来负责,它的java代码和JNI代码分别位于: frameworks/base/core/java/Android/hardware/SensorManager.java frameworks/base/core/jni/Android_hardware_SensorManager.cpp Android framework中与sensor通信的是sensorService.java和sensorManager.java。 sensorService.java的具体通信是通过JNI调用sensorService.cpp中的方法实现的。 sensorManager.java的具体通信是通过JNI调用sensorManager.cpp中的方法实现的。 sensorService.cpp和sensorManger.cpp通过hardware.c与sensor.so通信。其中sensorService.cpp实现对sensor的状态控制,sensorManger.cpp实现对sensor的数据控制。 sensor.so通过ioctl控制sensor driver的状态,通过打开sensor driver对应的设备文件读取G-sensor采集的数据。 Android SDK提供了4个类来于sensor通信,分别为 sensor,sensorEvent,sensorEventListener,sensorManager。其中 sensorEventListener用来在sensorManager中注册需要监听的sensor类型。 sensorManager.java提供registrater(),unregistrater()接口供sensorEventListener使用。 sensorManager.java不断轮询从sensor.so中取数据。取到数据后送给负责监听此类型sensor的 sensorEventListener.java。sensorEventListener.java通过在sensorManager.java中注册可以监听特定类型的sensor传来的数据。 系统启动时执行systemProcess,会启动sensorService.java,在sensorService.java的构造函数中调用JNI方法_sensor_control_init()。 sensorService.cpp中相应的方法Android_int()会被执行。该函数会调用hardware.c中的方法hw_get_mole()此函数又通过调用load()函数在system/lib/hw下查找sensor.so 查找时会根据harware.c中定义好的sensor.*.so的扩展名的顺序查找,找到第一个匹配的时候即停止,并将该sensor.so中定义好的一个全局变量HAL_MODULE_INFO_SYM带回。该变量包含的一个 重要信息是它的一个成员结构变量中包含的一个函数指针open,该指针所指函数会对一个device结构变量赋值,从而带出sensorService.cpp和sensorManager.cpp与sensor通信所需要的全部信息。 device结构变量有两种变体分别供sensorService.cpp和sensorManaer.cpp使用。其中主要是一些函数指针指向与sensor通信的函数。 sensorService.cpp和sensorManager.cpp在得到HAL_MODULE_INFO_SYM结构后都会调用 sensors.h的inline函数open()通过HAL_MODULE_INFO_SYM的open函数指针将所需的device信息取回。 系统在启动activityManager.java时,它会启动sensorManager.java,它也会调用hardware.c中的方法hw_get_mole()带回HAL_MODULE_INFO_SYM。
‘拾’ android 判断是否有gsensor
Android中sensor在Android系统架构中的位置及其工作。方框图如下:
从以上方框图中,可以看出Android中sensor在系统分为四层:驱动层(Sensor Driver)、硬件抽象层(Native)、中间层(Framework)、应用层(Java)。硬件抽象层与中间层可以合并一起作为Framework层。
针对我们xx这里一个具体的Gsensor,下面将以具体的源码形式来讲解以上的这个系统框图。