`
dowhathowtodo
  • 浏览: 780973 次
文章分类
社区版块
存档分类
最新评论

Android有关Sensor的源码总结

 
阅读更多

原文地址:

http://blog.csdn.net/JerryMo06/archive/2010/04/15/5487476.aspx

虽然这篇文章写得很差,因为赶时间,所以就匆匆忙忙地写出来自己作一个笔记。但是我想对大家应该有一点帮助。

1 、有关 sensor Java 应用程序的编程(以注册多个传感器为例,这程序是我临时弄出来的,可能有错)

package com.sensors.acc;

import android.app.Activity;

import android.os.Bundle;

import android.util.Log;

import android.widget.TextView;

import android.hardware.SensorManager;

import android.hardware.Sensor;

import android.hardware.SensorEvent;

import android.hardware.SensorEventListener;

public class acc extends Activity {

float x , y , z ;

SensorManager sensormanager = null ;

Sensor accSensor = null ;

Sensor lightSensor = null ;

Sensor proximitySensor = null ;

TextView accTextView = null ;

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super .onCreate(savedInstanceState);

setContentView(R.layout. main );

sensormanager = (SensorManager)getSystemService( SENSOR_SERVICE );

accSensor = sensormanager .getDefaultSensor(Sensor. TYPE_ACCELEROMETER );

lightSensor = sensormanager .getDefaultSensor(Sensor. TYPE_LIGHT );

proximitySensor = sensormanager .getDefaultSensor(Sensor. TYPE_PROXIMITY );

accTextView = (TextView)findViewById(R.id. textview_name );

}

SensorEventListener lsn = new SensorEventListener() {

public void onSensorChanged(SensorEvent e) {

if (e. sensor == accSensor ) {

Log.d ( "sensor" , "found acc sensor" );

x = e. values [SensorManager. DATA_X ];

y = e. values [SensorManager. DATA_Y ];

z = e. values [SensorManager. DATA_Z ];

accTextView .setText( "x = " + x + ", /ny = " + y + ", /nz = " + z );

}

else if (e. sensor == lightSensor ) {

Log.d ( "sensor" , "found light sensor" );

accTextView .setText( "data is " + e. values [0]);

}

else if (e. sensor == proximitySensor ) {

Log.d ( "sensor" , "found proximity sensor" );

accTextView .setText( "distance is " + e. values [0]);

}

// Log.d("sensor", "found acc sensor");

// Log.d("sensor", "x = " + x + ", y = " + y + ", z = " + z);

// accTextView.setText("x = " + x + ", /ny = " + y + ", /nz = " + z);

}

public void onAccuracyChanged(Sensor s, int accuracy) {

}

};

@Override

protected void onResume() {

super .onResume(); // register this class as a listener for the orientation and accelerometer sensors

sensormanager .registerListener( lsn , accSensor , SensorManager. SENSOR_DELAY_NORMAL );

sensormanager .registerListener( lsn , lightSensor , SensorManager. SENSOR_DELAY_NORMAL );

sensormanager .registerListener( lsn , proximitySensor , SensorManager. SENSOR_DELAY_NORMAL );

// sensormanager.unregisterListener(lsn );

}

@Override

protected void onStop() { // unregister listener

sensormanager .unregisterListener( lsn, accSensor );

sensormanager.unregisterListener(lsn, lightSensor);

sensormanager.unregisterListener(lsn, proximitySensor);

super .onStop();

}

}

onCreate() 函数中,调用 getSystemService( SENSOR_SERVICE ) 初始化一个 SensorManager 实例,为什么要用 getSystemService 函数,而不直接用 new SensorManager 呢?我们看此函数的实现,在 ApplicationContext.java 中,

if (SENSOR_SERVICE.equals(name)) {

return getSensorManager();

然后 getSensorManager() 的实现


private SensorManager getSensorManager() {

synchronized (mSync) {

if (mSensorManager == null) {

mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());

}

}

return mSensorManager;

}

看到没有?初始化 SensorManager 的时候需要 mMainThread.getHandler().getLooper() 这个参数,之个应该是用来传递消息用的,在 SensorManager 类的构造函数中会把此参数传给类成员 mMainLooper 。如果用 new SensorManager() 就需要另外获取 mainLooper 参数传递进去。

2 、在 android 中跟 sensor 有关的一些文件有 SensorManager.java ,位于 frameworks/base/core/java/android/hardware 目录下, SensorService.java ,位于 frameworks/base/services/java/com/android/server 目录下, android_hardware_SensorManager.cpp ,位于 frameworks/base/core/jni/ 目录下,与 SensorManager.java 相对应, com_android_server_SensorService.cpp ,在 frameworks/base/services/jni/ 目录下,与 SensorService.java 相对应。还有 SystemServer.java 文件, Hardware/Libhardware/Include/Hardware 目录下的 Sensor.h 头文件。另外我们需要根据 Sensor.h 实现自己的一个源文件,一般取名为 sensors_xxx.c 或者 sensors_xxx.cpp

3 SensorManager 类分析

有几个函数比较重要,必须清晰理解它们的实现,才能了解整个传感器系统的实现。从而更好地去实现硬件抽象层的实现。几个比较重要的函数有构造函数 SensorManager(), registerListener() unregisterListener() ,其中 registerListener() unregisterListener() 有多个,标志为 @Deprecated 的是过时的,就不要看了。

1 )构造函数 SensorManager(Looper mainLooper)

这个函数首先获取得传感器系统服务,并赋给类成员 mSensorService

mSensorService = ISensorService.Stub.asInterface(

ServiceManager.getService(Context.SENSOR_SERVICE));

这里我要说一句,就是关于这个传感器系统服务,很多书上都说用 getSystemService() 是获得传感器的系统服务,而它返回的是 SensorManager 类型,所以以为整个系统都是使用同一个 SensorManager 类的实例,以为我们在任何地方使用的 SensorManager 实例都是同一个,它们的公共成员是共享的。但是经过这两天的分析,这种说法是错误的。其实每次调用 getSystemService() 函数时都初始化一个新的 SensorManager 实例,而这个 SensorManager 实例会在构造函数里通过取得传感器系统服务 SensorService 来实现对下层传感器的一些控制。而这个 SensorService 才是系统的传感器服务,说服务,不如说它只是 SensorService 类的一个实例罢了。它只在系统初始化时初始化一次。 Android 中的系统服务机制应该跟传感器的都差不多一个样,都是由不同的 Manager 调用下层相同的 Service 。你可以列举其它的 Manager 。那它是什么时候初始化呢?它是系统初始化在 SystemServer 进程里创建的, SystemServer 是一个管理很多系统服务的进程,我们转到 SystemServer. main 函数里,可以看到一直到调用 int2() 函数,它会创建一个 ServerThread ,最终调用 AdbSettingsObserver (注:应该是ServerThread) 类的 run() 函数,在 run() 函数里有这么有一句

// Sensor Service is needed by Window Manager, so this goes first

Log.i(TAG, "Sensor Service");

ServiceManager.addService(Context.SENSOR_SERVICE, new SensorService(context));

这里就创建 SensorService 实例了。在创建这个实例时会在 SensorService 构造函数中调用 jni 函数 public SensorService(Context context) {

if (localLOGV) Log.d(TAG, "SensorService startup");

_sensors_control_init();

}

我们看 _sensors_control_init(); 对应的为

static jint

android_init(JNIEnv *env, jclass clazz)

{

sensors_module_t* module;

if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {

if (sensors_control_open(&module->common, &sSensorDevice) == 0) {

const struct sensor_t* list;

int count = module->get_sensors_list(module, &list);

return count;

}

}

return 0;

}

它主要调用了 sensor.h 中的 sensors_control_open()

static inline int sensors_control_open(const struct hw_module_t* module,

struct sensors_control_device_t** device) {

return module->methods->open(module,

SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);

}

之后在系统任何地方使用的都是这个 SensorService 实例。最后 run() 函数调用 Looper.loop(); 就进行消息循环等待了,这就是 SystemServer 进程的消息服务了。这才真正叫做系统服务嘛。

我们继续看 SensorManager 类的构造函数,取得 SensorService 后,

nativeClassInit();

这是一个 jni 函数, SensorManager 类调用的 jni 函数都在 com_android_server_SensorService.cpp 里,我们看这函数

static void

nativeClassInit (JNIEnv *_env, jclass _this)

{

jclass sensorClass = _env->FindClass("android/hardware/Sensor");

SensorOffsets& sensorOffsets = gSensorOffsets;

sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;");

sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");

sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");

sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I");

sensorOffsets.type = _env->GetFieldID(sensorClass, "mType", "I");

sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F");

sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");

sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");

}

这个函数只是获取和设置一些信息吧,我们不关心。接着

sensors_module_init();

我们看这函数

static jint

sensors_module_init(JNIEnv *env, jclass clazz)

{

int err = 0;

sensors_module_t const* module;

err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);

if (err == 0)

sSensorModule = (sensors_module_t*)module;

return err;

}

它获取了 sensor 的模块信息,并把它赋给 sSensorModule 全局变量,之后传的 modules 参数都为这个。

接着在构造函数里

final ArrayList<Sensor> fullList = sFullSensorsList;

int i = 0;

do {

Sensor sensor = new Sensor();

i = sensors_module_get_next_sensor(sensor, i);

if (i>=0) {

Log.d(TAG, "found sensor: " + sensor.getName() +

", handle=" + sensor.getHandle());

sensor.setLegacyType(getLegacySensorType(sensor.getType()));

fullList.add(sensor);

sHandleToSensor.append(sensor.getHandle(), sensor);

}

} while (i>0);

这里主要是通过 jni 函数 sensors_module_get_next_sensor(sensor, i); 获取传感器列表,并把它加入自己的 fullList 列表中。我们看 sensors_module_get_next_sensor() 函数

static jint

sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)

{

if (sSensorModule == NULL)

return 0;

SensorOffsets& sensorOffsets = gSensorOffsets;

const struct sensor_t* list;

int count = sSensorModule->get_sensors_list(sSensorModule, &list);

if (next >= count)

return -1;

list += next;

jstring name = env->NewStringUTF(list->name);

jstring vendor = env->NewStringUTF(list->vendor);

env->SetObjectField(sensor, sensorOffsets.name, name);

env->SetObjectField(sensor, sensorOffsets.vendor, vendor);

env->SetIntField(sensor, sensorOffsets.version, list->version);

env->SetIntField(sensor, sensorOffsets.handle, list->handle);

env->SetIntField(sensor, sensorOffsets.type, list->type);

env->SetFloatField(sensor, sensorOffsets.range, list->maxRange);

env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);

env->SetFloatField(sensor, sensorOffsets.power, list->power);

next++;

return next<count ? next : 0;

}

它主要是调用 HAL 层的 get_sensors_list() 函数取得传感器列表信息。

接着在 sensorManger 构造函数最后

sSensorThread = new SensorThread();

创建一个 SensorThread() 线程。但并未运行,但在 SensorThread 类的构造函数里会执行 jni 函数 sensors_data_init();

我们看此函数 static jint

sensors_data_init(JNIEnv *env, jclass clazz)

{

if (sSensorModule == NULL)

return -1;

int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);

return err;

}

它调用了 HAL 层的 sensors_data_open 函数,而这个函数位于 sensor.h 中,它调用的是

static inline int sensors_data_open(const struct hw_module_t* module,

struct sensors_data_device_t** device) {

return module->methods->open(module,

SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);

}

Modules->methods->open 函数。而在 SensorThread 类的析构函数 finalize() 里会调用

sensors_data_uninit();

static jint

sensors_data_uninit(JNIEnv *env, jclass clazz)

{

int err = 0;

if (sSensorDevice) {

err = sensors_data_close(sSensorDevice);

if (err == 0)

sSensorDevice = 0;

}

return err;

}

sensor.h

static inline int sensors_data_close(struct sensors_data_device_t* device) {

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

}

那什么时候 sSensorThread 线程会运行呢?我们在下面看 registerListener() 函数。

2 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate) {

return registerListener(listener, sensor, rate, null);

}

它调用的是 public boolean registerListener(SensorEventListener listener, Sensor sensor, int rate,

Handler handler)

在这函数中,先验证 rate ,然后检测注册的 listener 在不在本类的 sListeners 列表中。

for (ListenerDelegate i : sListeners) {

if (i.getListener() == listener) {

l = i;

break;

}

}

如果不在就申请一个 listener ,并把它加入全局列表 sListener 中,并调用 mSensorService enableSensor() 函数使能传感器,这个 enableSensor() 函数最终会调用 HAL 层的 active 函数和 set_delay() 函数,使用后然后判断 sListener 列表是否为空,当然,第一次为空时加入一个新的 listener 就不为空了,此时就执行 sSensorThread startLocked 运行 sSensorThread 线程了

l = new ListenerDelegate(listener, sensor, handler);

result = mSensorService.enableSensor(l, name, handle, delay);

if (result) {

sListeners.add(l);

sListeners.notify();

}

if (!sListeners.isEmpty()) {

sSensorThread.startLocked(mSensorService);

}

另一方面,如果注册的 listener sListeners 列表中,则先调用 mSensorService enableSensor() 函数使能传感器,然后把注册的传感器加入到已存在的 listener 中。

result = mSensorService.enableSensor(l, name, handle, delay);

if (result) {

l.addSensor(sensor);

}

接下来我们看看 startLocked 函数,它在 SensorThread 中,

void startLocked(ISensorService service) {

try {

if (mThread == null) {

Bundle dataChannel = service.getDataChannel();

mThread = new Thread(new SensorThreadRunnable(dataChannel),

SensorThread.class.getName());

mThread.start();

}

} catch (RemoteException e) {

Log.e(TAG, "RemoteException in startLocked: ", e);

}

}

第一次 mThread null ,然后它调用了 service.getDataChannel() 函数,此函数在 SensorService 类中,主要调用了 jni 函数 _sensors_control_open()

public Bundle getDataChannel() throws RemoteException {

// synchronize so we do not require sensor HAL to be thread-safe.

synchronized(mListeners) {

return _sensors_control_open();

}

}

SensorService 类中调用的 jni 函数主要都在 com_android_server_SensorService.cpp 文件 中,我们看一下这个函数

static jobject

android_open(JNIEnv *env, jclass clazz)

{

native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);

if (!handle) {

return NULL;

}

// new Bundle()

jobject bundle = env->NewObject(

gBundleOffsets.mClass,

gBundleOffsets.mConstructor);

if (handle->numFds > 0) {

jobjectArray fdArray = env->NewObjectArray(handle->numFds,

gParcelFileDescriptorOffsets.mClass, NULL);

for (int i = 0; i < handle->numFds; i++) {

// new FileDescriptor()

jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,

gFileDescriptorOffsets.mConstructor);

env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);

// new ParcelFileDescriptor()

jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,

gParcelFileDescriptorOffsets.mConstructor, fd);

env->SetObjectArrayElement(fdArray, i, pfd);

}

// bundle.putParcelableArray("fds", fdArray);

env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,

env->NewStringUTF("fds"), fdArray);

}

if (handle->numInts > 0) {

jintArray intArray = env->NewIntArray(handle->numInts);

env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);

// bundle.putIntArray("ints", intArray);

env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,

env->NewStringUTF("ints"), intArray);

}

// delete the file handle, but don't close any file descriptors

native_handle_delete(handle);

return bundle;

}

它主要调用了 HAL 层的 open_data_source() 函数。取得一些文件描述符等信息。

接下来 SensorThread 创建一个线程,调用 start() 就进入 SensorThreadRunnable 类的 run() 函数了,所以我们接着去看 run() 函数,它首先调用 open() 函数

if (!open()) {

return;

}

open() 函数中调用了 jni 函数 sensors_data_open(fds, ints);

static jint

sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)

{

jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");

jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");

int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);

int numInts = (intArray ? env->GetArrayLength(intArray) : 0);

native_handle_t* handle = native_handle_create(numFds, numInts);

int offset = 0;

for (int i = 0; i < numFds; i++) {

jobject fdo = env->GetObjectArrayElement(fdArray, i);

if (fdo) {

handle->data[offset++] = env->GetIntField(fdo, fieldOffset);

} else {

handle->data[offset++] = -1;

}

}

if (numInts > 0) {

jint* ints = env->GetIntArrayElements(intArray, 0);

for (int i = 0; i < numInts; i++) {

handle->data[offset++] = ints[i];

}

env->ReleaseIntArrayElements(intArray, ints, 0);

}

// doesn't take ownership of the native handle

return sSensorDevice->data_open(sSensorDevice, handle);

}

这函数最终调用了 HAL 层的 data_open() ,之后 run() 函数就进入一个 while 循环了。

while (true) {

// wait for an event

final int sensor = sensors_data_poll(values, status, timestamp);

int accuracy = status[0];

synchronized (sListeners) {

if (sensor == -1 || sListeners.isEmpty()) {

if (sensor == -1) {

// we lost the connection to the event stream. this happens

// when the last listener is removed.

Log.d(TAG, "_sensors_data_poll() failed, we bail out.");

}

// we have no more listeners or polling failed, terminate the thread

sensors_data_close();

mThread = null;

break;

}

final Sensor sensorObject = sHandleToSensor.get(sensor);

if (sensorObject != null) {

// report the sensor event to all listeners that

// care about it.

final int size = sListeners.size();

for (int i=0 ; i<size ; i++) {

ListenerDelegate listener = sListeners.get(i);

if (listener.hasSensor(sensorObject)) {

// this is asynchronous (okay to call

// with sListeners lock held).

listener.onSensorChangedLocked(sensorObject,

values, timestamp, accuracy);

}

}

}

}

它调用了 jni 函数 sensors_data_poll() 一直读数据。

static jint

sensors_data_poll(JNIEnv *env, jclass clazz,

jfloatArray values, jintArray status, jlongArray timestamp)

{

sensors_data_t data;

int res = sSensorDevice->poll(sSensorDevice, &data);

if (res >= 0) {

jint accuracy = data.vector.status;

env->SetFloatArrayRegion(values, 0, 3, data.vector.v);

env->SetIntArrayRegion(status, 0, 1, &accuracy);

env->SetLongArrayRegion(timestamp, 0, 1, &data.time);

}

return res;

}

把传感器得到的值都放在 value 数组中,根据返回的传感器标志 sensor ,把它分派给在 sListener 列表中所有的 listener ,如果 listener 中有监听这个 sensor ,就把它分派给这个 listener ,此时就会引起 onSensorChange() 了。

好了,获取传感器数据主要是这样一个途径。最后我们去分析一下 unregisterListener() 函数。

private void unregisterListener(Object listener) {

if (listener == null) {

return;

}

try {

synchronized (sListeners) {

final int size = sListeners.size();

for (int i=0 ; i<size ; i++) {

ListenerDelegate l = sListeners.get(i);

if (l.getListener() == listener) {

// disable all sensors for this listener

for (Sensor sensor : l.getSensors()) {

String name = sensor.getName();

int handle = sensor.getHandle();

mSensorService.enableSensor(l, name, handle, SENSOR_DISABLE);

}

sListeners.remove(i);

break;

}

}

}

} catch (RemoteException e) {

Log.e(TAG, "RemoteException in unregisterListener: ", e);

}

}

不用想这个函数会做一些与 registerListener 相反的事情,至少差不多。它先在 sListeners 列表中找到这个 listener ,然后先调用 enableSensor() 函数禁止这个传感器。我们跟踪一下这函数,在 SensorService 类中。

synchronized(mListeners) {

if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {

Log.w(TAG, "could not enable sensor " + sensor);

return false;

}

Listener l = null;

int minDelay = enable;

for (Listener listener : mListeners) {

if (binder == listener.mToken) {

l = listener;

}

if (minDelay > listener.mDelay)

minDelay = listener.mDelay;

}

if (l == null && enable!=SENSOR_DISABLE) {

l = new Listener(binder);

binder.linkToDeath(l, 0);

mListeners.add(l);

mListeners.notify();

}

if (l == null) {

// by construction, this means we're disabling a listener we

// don't know about...

Log.w(TAG, "listener with binder " + binder +

", doesn't exist (sensor=" + name + ", id=" + sensor + ")");

return false;

}

if (minDelay >= 0) {

_sensors_control_set_delay(minDelay);

}

if (enable != SENSOR_DISABLE) {

l.addSensor(sensor, enable);

} else {

l.removeSensor(sensor);

deactivateIfUnusedLocked(sensor);

if (l.mSensors == 0) {

mListeners.remove(l);

binder.unlinkToDeath(l, 0);

mListeners.notify();

}

}

if (mListeners.size() == 0) {

_sensors_control_wake();

_sensors_control_close();

}

}

return true;

你们看到它的实现了吧。如果 enable true 的话,就调用 _sensors_control_activate() ,如果是 false 的话,就调用 deactivateIfUnusedLocked() ,它们最终都会调用 HAL 层的 active() 函数。最后,如果是禁止传感器的话,如果 mListeners 为空了,它就会调用

_sensors_control_wake();

_sensors_control_close();

这两个 jni 函数,最终会调用 HAL 层的 wake() close_data_source() 函数。当调用 wake() 函数时,会使 SensorManager 类线程的 run() 函数中的 sensor_data_poll() 函数立即返回,此时在 run() 函数中调用 sensors_data_close(); 最终会调用 HAL 层的 data_close() 函数。至此,一个传感器从初始到结束的流程就分析完了。

所以在 java 使用一个传感器在 HAL 层具体调用的函数流程为:

首先, sensors_control_open() ,只在系统初始化时调用一次。用来初始化 control_device 结构体。

以下的是每次使用传感器一般经过的流程,注意,是一般而已,有些并不执行

1 sensors_data_open

2 get_sensors_list

3 activate

4 set_delay

5 open_data_source

6 data_open

7 poll

一直读数据。。。。。。。。。。。

退出时

8 activate

9 sensors_control_close

10 data_close

当然其它的细节你们可以继续去研究。也可以在我博客里提出来大家交流和讨论一下!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics