阅读android有关sensor的源码总结

  • Post author:
  • Post category:其他


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




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



类的



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







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



版权声明:本文为JerryMo06原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。