最近工作上有碰到sensor的相关问题,正好分析下其流程作个笔记。

这个笔记分三个部分:

  1. sensor硬件和驱动的工作机制
  2. sensor 上层app如何使用
  3. 从驱动到上层app这中间的流程是如何

Sensor硬件和驱动的工作机制

先看看Accerometer +Gyro Sensor的原理图:

总结起来分四个部分(电源,地,通信接口,中断脚)。电源和地与平台和芯片本身有关系,与我们分析的没有多少关系,根据sensor的特性保证sensor正常工作的上电时序。关于通信接口,sensor与ap之间通信一般有两种接口(I2C/SPI)。因sensor数据量不大,I2C的速度足矣,目前使用I2C的居多。SDA是I2C的数据线,SCL是I2C的clock线。关于中断脚就是INT。Sensor有两个工作模式。一种是主动上报数据(每时每刻将获取到的数据上报给系统),另个一种是中断模式(当数据的变化大于了之前设置的触发条件),比如手机翻转大于45度,就会将当前的变化及当前数据上报给系统。

Sensor上层app的使用

先要注册指定sensor的事件监听,然在在有事件上报上来时,获取上报的数据。

具体代码如下:

  1. 1 SensorManager mSensorManager = (SensorManager)mContext.getSystemService(Context.SENSOR_SERVICE);
  2. 2 Sensor mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  3. 3
  4. 4 mSensorManager.registerListener(mSensorListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
  5. 5 /*
  6. 6 public static final int SENSOR_DELAY_FASTEST = 0;
  7. 7 public static final int SENSOR_DELAY_GAME = 1;
  8. 8 public static final int SENSOR_DELAY_UI = 2;
  9. 9 public static final int SENSOR_DELAY_NORMAL = 3;
  10. 10 上报的速度可以根据需求来选择
  11. 11 */
  12. 12
  13. 13 SensorEventListener mSensorListener = new SensorEventListener(){
  14. 14 public void onAccuracyChanged(Sensor arg0, int arg1){
  15. 15 }
  16. 16
  17. 17 public void onSensorChanged(SensorEvent event){
  18. 18 if(event.sensor == null){
  19. 19 return;
  20. 20 }
  21. 21 Log.d(TAG, "onSensorChanged");
  22. 22 if(Sensor.TYPE_ACCELEROMETER == event.sensor.getType()) {
  23. 23 mGsensor = (float)event.values[SensorManager.DATA_Z];
  24. 24 mSensorManager.unregisterListener(this);
  25. 25 Log.e(TAG, "mgsensor = " + mGsensor);
  26. 26 mOnSensorChangedFlag = false;
  27. 27 }
  28. 28 }
  29. 29 }

从驱动到上层App这中间的流程如何

前面二段分别说了驱动上报数据和app读取数据,但中间的流程是如何的呢,这个是此篇博客的重点了。

驱动层上报数据后,HAL层怎么处理呢?这个属于input hal层的接收和分发了。来,我们来啃啃这个骨头:

frameworks/base/core/java/android/app/SystemServiceRegistry.java

  1. registerService(Context.SENSOR_SERVICE, SensorManager.class,
  2. new CachedServiceFetcher<SensorManager>() {
  3. @Override
  4. public SensorManager createService(ContextImpl ctx) {
  5. return new SystemSensorManager(ctx.getOuterContext(),
  6. ctx.mMainThread.getHandler().getLooper());
  7. }});
  1. mContext.getSystemService(Context.SENSOR_SERVICE) 返回的就是SystemSensorManager 的对象(也是继承SensorManager 类)。
  2.  
  3. frameworks/base/core/java/android/hardware/SensorManager.java
  1. public Sensor getDefaultSensor(int type) {
  2. ......................................................................
  3. List<Sensor> l = getSensorList(type);
  4. boolean wakeUpSensor = false;
  5.  
  6. if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION ||
  7. type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE ||
  8. type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE ||
  9. type == Sensor.TYPE_WRIST_TILT_GESTURE) {
  10. wakeUpSensor = true;
  11. }
  12. //返回支持唤醒的sensor
  13. for (Sensor sensor : l) {
  14. if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;
  15. }
  16. }

我们再看看getSensorList这里面有啥玩意。。。。

  1. public List<Sensor> getSensorList(int type) {
  2. .......................................................................
  3. final List<Sensor> fullList = getFullSensorList();
  4. //然后再种所有sensor中找出对应的sensor
  5. for (Sensor i : fullList) {
  6. if (i.getType() == type)
  7. list.add(i);
  8. }
  9. return list
  1. getFullSensorList这个函数返回的是mFullSensorsList
    mFullSensorListSystemSensorManager 遍历所有的sensor得到的集合。
    下一步我们再来看看registerListener是怎么回事。
    frameworks/base/core/java/android/hardware/SystemSensorManager.java
  1. protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
  2. synchronized (mSensorListeners) {
  3. //先查看下此sensor的监听队列是否已经存在,如果不存在,就重新new个
  4. SensorEventQueue queue = mSensorListeners.get(listener);
  5. if (queue == null) {
  6. queue = new SensorEventQueue(listener, looper, this, fullClassName);
  7. mSensorListeners.put(listener, queue);
  8. return true;
  9. } else {
  10. return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);
  11. }

到这里就明显是一个消息队列回调的问题了,肯定是发现消息队列里有消息时就会回调具体的事件。我们继续撸代码。

  1. static final class SensorEventQueue extends BaseEventQueue {
  2. protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
  3. long timestamp) {
  4. ......................................................
  5. // call onAccuracyChanged() only if the value changes
  6. final int accuracy = mSensorAccuracies.get(handle);
  7. if ((t.accuracy >= ) && (accuracy != t.accuracy)) {
  8. mSensorAccuracies.put(handle, t.accuracy);
  9. mListener.onAccuracyChanged(t.sensor, t.accuracy);
  10. }
  11. mListener.onSensorChanged(t);
  12. }
  13. }

从这里就可以看我们listener里实现的onAccuracyChanged,onSensorChanged是怎么被调用。

frameworks/base/core/java/android/hardware/SensorEventListener.java

  1. public interface SensorEventListener {
  2. public void onSensorChanged(SensorEvent event);
  3. public void onAccuracyChanged(Sensor sensor, int accuracy);

就是一个接口,里面声明两个函数。

看到回调是在dispatchSensorEvent里做的,看看是谁调用的。。。

frameworks/base/core/jni/android_hardware_SensorManager.cpp

  1. class Receiver : public LooperCallback {
  2. virtual int handleEvent(int fd, int events, void* data) {
  3.  
  4. ASensorEvent buffer[];
  5. while ((n = q->read(buffer, )) > ) {
  6. for (int i= ; i<n ; i++) {
  7. if (buffer[i].type == SENSOR_TYPE_META_DATA) {
  8. // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
  9. // method.
  10. if (receiverObj.get()) {
  11. env->CallVoidMethod(receiverObj.get(),
  12. gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
  13. buffer[i].meta_data.sensor);
  14. }
  15. } else {
  16. if (receiverObj.get()) {
  17. env->CallVoidMethod(receiverObj.get(),
  18. gBaseEventQueueClassInfo.dispatchSensorEvent,
  19. buffer[i].sensor,
  20. mScratch,
  21. status,
  22. buffer[i].timestamp);
  23. }
  24.  
  25. }
  26. }
  27. }
  28. }

读到的数据,根据数据的类型去回调不同的接口。dispatchSensorEvent就是在这里被调用的。

handleEvent这个是一个典型的eventQueue这事件处理,具体就不在这里分析了。

 回调这些都有分析了,那事件是哪里加入到消息队列中的,那些消息又是怎么来的呢,话说问题问对了,就能找到往下查的路了。。哈哈


理论这些肯定会有sensor服务在开机的时候启动的,那服务在哪里,是怎么启动的呢。。。

frameworks/base/services/java/com/android/server/SystemServer.java

  1. private void startBootstrapServices() {
  2. ...................................................
  3. startSensorService();
  4. }

这个startSensorService是个jni函数,调用的是:

frameworks/base/services/core/jni/com_android_server_SystemServer.cpp

  1. static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
  2. //创建一个线程做sensorinit的工作
  3. pthread_create( &sensor_init_thread, NULL, &sensorInit, NULL);
  4.  
  5. void* sensorInit(void *arg) {
  6. SensorService::instantiate();

sensorService服务就做初始化了,服务启动时会做threadLoop(),

  1. bool SensorService::threadLoop()
  2. {
  3. ALOGD("nuSensorService thread starting...");
  4.  
  5. const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
  6. const size_t numEventMax = minBufferSize / ( + mVirtualSensorList.size());
  7.  
  8. //device初始化
  9. SensorDevice& device(SensorDevice::getInstance());
  10. const size_t vcount = mVirtualSensorList.size();
  11.  
  12. const int halVersion = device.getHalDeviceVersion();
  13. do {
  14. //调用device.poll
  15. ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
  16. if (count < ) {
  17. ALOGE("sensor poll failed (%s)", strerror(-count));
  18. break;
  19. }
  20. }

再看看SensorDevice 里初始化和poll里做了啥 :

  1. SensorDevice::SensorDevice()
  2. : mSensorDevice(),
  3. mSensorModule()
  4. {
      //get HAL module
  5. status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
  6. (hw_module_t const**)&mSensorModule);
  7.  
  8. ALOGE_IF(err, "couldn't load %s module (%s)",
  9. SENSORS_HARDWARE_MODULE_ID, strerror(-err));
  10.  
  11. if (mSensorModule) {
         //open HAL module
  12. err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
  13. ...................................................
  14. }

SensorDevice初始化做了两个动作,一个是获取sensor HAL module,紧接着打开sensor hal module。

再一起看年poll里做啥了,

  1. ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
  2. if (!mSensorDevice) return NO_INIT;
  3. ssize_t c;
  4. do {
  5. c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
  6. buffer, count);
  7. } while (c == -EINTR);
  8. return c;
  9. }

poll也是调用 的是Hal module里的poll。

那sensor HAL里做了啥呢,模块做了啥呢?

sensor hal路径:hardware/libhardware/modules/sensors/

hardware/libhardware/modules/sensors/multihal.cpp

  1. static int open_sensors(const struct hw_module_t* hw_module, const char* name,
  2. struct hw_device_t** hw_device_out) {
  3. ALOGV("open_sensors begin...");
  4. //初始化加载高通的库
  5. lazy_init_modules();
  6.  
  7. // Create proxy device, to return later.
  8. sensors_poll_context_t *dev = new sensors_poll_context_t();
  9. memset(dev, , sizeof(sensors_poll_device_1_t));
  10. dev->proxy_device.common.tag = HARDWARE_DEVICE_TAG;
  11. dev->proxy_device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
  12. dev->proxy_device.common.module = const_cast<hw_module_t*>(hw_module);
  13. dev->proxy_device.common.close = device__close;
  14. dev->proxy_device.activate = device__activate;
  15. dev->proxy_device.setDelay = device__setDelay;
  16. dev->proxy_device.poll = device__poll;
  17. dev->proxy_device.batch = device__batch;
  18. dev->proxy_device.flush = device__flush;
  19. .......................................
  20. }

我们看看lazy_init_modules()这个,是把指定的的hal so加载起来。。

  1. /*
  2. 482 * Ensures that the sub-module array is initialized.
  3. 483 * This can be first called from get_sensors_list or from open_sensors.
  4. 484 */
  5. static void lazy_init_modules() {
  6. pthread_mutex_lock(&init_modules_mutex);
  7. if (sub_hw_modules != NULL) {
  8. pthread_mutex_unlock(&init_modules_mutex);
  9. return;
  10. }
  11. std::vector<std::string> *so_paths = new std::vector<std::string>();
  12. /*
  13. 482 * Ensures that the sub-module array is initialized.
  14. 483 * This can be first called from get_sensors_list or from open_sensors.
  15. 484 */
  16. static void lazy_init_modules() {
  17. pthread_mutex_lock(&init_modules_mutex);
  18. if (sub_hw_modules != NULL) {
  19. pthread_mutex_unlock(&init_modules_mutex);
  20. return;
  21. }
  22. std::vector<std::string> *so_paths = new std::vector<std::string>();
  23. get_so_paths(so_paths);
  24.  
  25. // dlopen the module files and cache their module symbols in sub_hw_modules
  26. sub_hw_modules = new std::vector<hw_module_t *>();
  27. dlerror(); // clear any old errors
  28. const char* sym = HAL_MODULE_INFO_SYM_AS_STR;
  29. for (std::vector<std::string>::iterator it = so_paths->begin(); it != so_paths->end(); it++) {
  30. const char* path = it->c_str();
  31. void* lib_handle = dlopen(path, RTLD_LAZY);
  32. if (lib_handle == NULL) {
  33. ALOGW("dlerror(): %s", dlerror());
  34. } else {
  35. ALOGI("Loaded library from %s", path);
  36. ALOGV("Opening symbol \"%s\"", sym);
  37. // clear old errors
  38. dlerror();
  39. struct hw_module_t* module = (hw_module_t*) dlsym(lib_handle, sym);
  40. const char* error;
  41. if ((error = dlerror()) != NULL) {
  42. ALOGW("Error calling dlsym: %s", error);
  43. } else if (module == NULL) {
  44. ALOGW("module == NULL");
  45. } else {
  46. ALOGV("Loaded symbols from \"%s\"", sym);
  47. sub_hw_modules->push_back(module);
  48. }
  49. }
  50. }
  51. pthread_mutex_unlock(&init_modules_mutex);
  52. }
  53. //获取的要加载so库的路径:/system/etc/sensors/hals.conf
  54. get_so_paths(so_paths);
  55.  
  56. // dlopen the module files and cache their module symbols in sub_hw_modules
  57. sub_hw_modules = new std::vector<hw_module_t *>();
  58. dlerror(); // clear any old errors
  59. const char* sym = HAL_MODULE_INFO_SYM_AS_STR;
  60. for (std::vector<std::string>::iterator it = so_paths->begin(); it != so_paths->end(); it++) {
  61. const char* path = it->c_str();
  62. void* lib_handle = dlopen(path, RTLD_LAZY);
  63. if (lib_handle == NULL) {
  64. ALOGW("dlerror(): %s", dlerror());
  65. } else {
  66. ALOGI("Loaded library from %s", path);
  67. ALOGV("Opening symbol \"%s\"", sym);
  68. // clear old errors
  69. dlerror();
  70. struct hw_module_t* module = (hw_module_t*) dlsym(lib_handle, sym);
  71. const char* error;
  72. if ((error = dlerror()) != NULL) {
  73. ALOGW("Error calling dlsym: %s", error);
  74. } else if (module == NULL) {
  75. ALOGW("module == NULL");
  76. } else {
  77. ALOGV("Loaded symbols from \"%s\"", sym);
  78. sub_hw_modules->push_back(module);
  79. }
  80. }
  81. }
  82. pthread_mutex_unlock(&init_modules_mutex);
  83. }

这个路径下就一个库:sensors.ssc.so

再来看看poll看名字就能猜到是从数据队列里等数据,看代码:

  1. int sensors_poll_context_t::poll(sensors_event_t *data, int maxReads) {
  2. ALOGV("poll");
  3. int empties = ;
  4. int queueCount = ;
  5. int eventsRead = ;
  6.  
  7. pthread_mutex_lock(&queue_mutex);
  8. queueCount = (int)this->queues.size();
  9. while (eventsRead == ) {
  10. while (empties < queueCount && eventsRead < maxReads) {
  11. SensorEventQueue* queue = this->queues.at(this->nextReadIndex);
  12. sensors_event_t* event = queue->peek();

确实是消息队列。。。

再来年看看加载的so库这个是高通的sensor hal库。

代码路径:vendor/qcom/proprietary/sensors/dsps/libhalsensors

看先从哪里插入数据的:

vendor/qcom/proprietary/sensors/dsps/libhalsensors/src/Utility.cpp

  1. bool Utility::insertQueue(sensors_event_t const *data_ptr){
  2. ..........................
  3. if (q_head_ptr == NULL) {
  4. /* queue is empty */
  5. q_tail_ptr = q_ptr;
  6. q_head_ptr = q_ptr;
  7. } else {
  8. /* append to tail and update tail ptr */
  9. q_tail_ptr->next = q_ptr;
  10. q_tail_ptr = q_ptr;
  11. }
  12. }

那看调用的有哪些呢?

Orientation.cpp (src): if (Utility::insertQueue(&la_sample)) {
PedestrianActivityMonitor.cpp (src): if (Utility::insertQueue(&sensor_data)) {
Pedometer.cpp (src): if (Utility::insertQueue(&la_sample)) {
PickUpGesture.cpp (src): if (Utility::insertQueue(&sensor_data)) {
QHeart.cpp (src): if (Utility::insertQueue(&la_sample)) {
RelativeMotionDetector.cpp (src): if (Utility::insertQueue(&sensor_data)) {
RotationVector.cpp (src): if (Utility::insertQueue(&la_sample)) {
Sensor.cpp (src): if (Utility::insertQueue(&flush_evt)){

....................................................................

都在各类sensor的processInd 这个函数中,每种sensor类型根据自身数据的特点,对其做数据结构做指定封装。也就是所谓的工厂模式。

有一个调用比较特别:SMGRSensor.cpp 中processReportInd函数,这个函数中

  1. void SMGRSensor::processReportInd(Sensor** mSensors, sns_smgr_periodic_report_ind_msg_v01* smgr_ind){
  2. ...............................
  3. handle = getHandleFromInd(smgr_ind->ReportId, smgr_data->DataType,
  4. smgr_data->SensorId);
  5. if (handle == - ) {
  6. HAL_LOG_ERROR(" %s: ReportId = %d DataType = %d SensorId = %d ", __FUNCTION__,
  7. smgr_ind->ReportId, smgr_data->DataType, smgr_data->SensorId);
  8. goto error;
  9. }
  10. /* Corresponds to screen orientation req, fill in the right type */
  11. if ((handle == HANDLE_ACCELERATION) && (smgr_ind->ReportId == HANDLE_MOTION_ACCEL)) {
  12. sensor_data.type = SENSOR_TYPE_SCREEN_ORIENTATION;
  13. sensor_data.sensor = HANDLE_MOTION_ACCEL;
  14. }
  15.  
  16. if (mSensors[handle] != NULL) {
  17. (static_cast<SMGRSensor*>(mSensors[handle]))->processReportInd(smgr_ind, smgr_data, sensor_data);
  18. }
  19. ................................
  20. if (Utility::insertQueue(&sensor_data)) {
  21. Utility::signalInd(data_cb);
  22. }
  23. }

这里根据smgr_data->DataType又做了一次工厂模式的分发处理:

  1. GyroscopeUncalibrated.cpp (src): FUNCTION: processReportInd
  2. GyroscopeUncalibrated.cpp (src):void GyroscopeUncalibrated::processReportInd(
  3. GyroscopeUncalibrated.cpp (src): HAL_LOG_DEBUG("GyroscopeUncalibrated::processReportInd");
  4. GyroscopeUncalibrated.h (inc): FUNCTION: processReportInd
  5. GyroscopeUncalibrated.h (inc): void processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  6. HallEffect.cpp (src): FUNCTION: processReportInd
  7. HallEffect.cpp (src):void HallEffect::processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  8. HallEffect.h (inc): FUNCTION: processReportInd
  9. HallEffect.h (inc): void processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  10. Humidity.cpp (src): FUNCTION: processReportInd
  11. Humidity.cpp (src):void Humidity::processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  12. Humidity.h (inc): FUNCTION: processReportInd
  13. Humidity.h (inc): void processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  14. IRGesture.cpp (src): FUNCTION: processReportInd
  15. IRGesture.cpp (src):void IRGesture::processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  16. IRGesture.h (inc): FUNCTION: processReportInd
  17. IRGesture.h (inc): void processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  18. Light.cpp (src): FUNCTION: processReportInd
  19. Light.cpp (src):void Light::processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  20. Light.h (inc): FUNCTION: processReportInd
  21. Light.h (inc): void processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  22. Magnetic.cpp (src): FUNCTION: processReportInd
  23. Magnetic.cpp (src):void Magnetic::processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind,
  24. Magnetic.h (inc): FUNCTION: processReportInd
  25. Magnetic.h (inc): void processReportInd(sns_smgr_periodic_report_ind_msg_v01* smgr_ind
  1. 又是根据类型不同,做了另一批类型sensor的处理。
    继续反向推导,processReportInd其它这个也是processBufferingInd 调用的,processBufferingInd也是processInd 调用的。这就和其它的sensor到统一战线上了。都是processInd处理的。
    关键就是这processInd了,这个是一个回调SMGRSensor_sensor1_cb函数里处理的。那这个回调是谁注册,又是什么调用的呢?
    vendor/qcom/proprietary/sensors/dsps/libhalsensors/src/SensorsContext.cpp
    这个里面会在SensorContext实例化时注册。
  1. SensorsContext::SensorsContext()
  2. : active_sensors(),
  3. is_accel_available(false),
  4. is_gyro_available(false),
  5. is_mag_available(false),
  6. is_prox_available(false),
  7. smgr_version()
  8. {
  9. 。。。。。。。。。。。。。。。。。。。
  10.  
  11. err = sensor1_open(&sensor_info_sensor1_cb->sensor1_handle, &context_sensor1_cb, (intptr_t)this);
  12. 。。。。。。。。。
  13. }

那得去撸代码啊,不然不知道啥时候回调context_sensor1_cb这个函数啊。。。

这个函数在另一个库中了libsensor1。。

这个函数做的事情比较多,分三部分:

  1. sensor1_open( sensor1_handle_s **hndl,
  2. sensor1_notify_data_cb_t data_cbf,
  3. intptr_t cb_data )
  4. {
  5. .........................
  6. sensor1_init();
  7. ............................
  8. sockfd = socket(AF_UNIX, SOCK_SEQPACKET, ))
  9. strlcpy(address.sun_path, SENSOR_CTL_SOCKET, UNIX_PATH_MAX);
  10. connect(sockfd, (struct sockaddr *)&address, len)
  11. .....................................
  12. libsensor_add_waiting_client(&cli_data);
  13. libsensor_add_client( &new_cli, false )
  14. .....................................
  15. }

那第一步先看看sensor1_init做了啥?

相当于创建了一个读线程,一直在poll读消息队列里的消息,读到消息后,会封装数据,然后发一个信息去唤醒另外一个线程,唤醒的线程后面再说。

第二步再看看,创建了一个socket(一个客户端socket),去连接服务端的socket(服务端的socket又是什么东东),上个读线程读到的消息就是从socket读到的消息(libsensor_read_socket),那一定是服务端socket发送过来的嘛。。。

第三步增加client,再看看这个又做了啥?

这里又创建了一个回调线程,等有消息来时,唤醒本线程,然后回调sensor.ssc.库里的context_sensor1_cb。这个线程就谁唤醒的呢,哈哈,大家就能想到就是init中的那个读线程嘛。

总结sensor1_open就是创建一个读线程从socket客户端中读数据,读到数据后,就回调sensor.ssc库中的context_sensor1_cb,进而上报数据做进一步回调。

那问题来了,那个socket服务端又是怎么回事呢。。。慢慢接近真相了。。。。


这时又出现了一个服务SensorDaemon:

代码路径:vendor/qcom/proprietary/sensors/dsps/sensordaemon

sns_main_setup 里创建了socket服务器端,然后监听客户端socket的监听,那什么时候往socket里写东西呢?

这就涉及另一个回调函数了sns_main_notify_cb。这个回调函数则好就是sensor1_open里注册的。这个sensor1_open 与 libsensor1里的sensor1_open不是同一个。

ok,那问题又来了,啥时候做的回调,和之前很类似,有一个读线程,初始化后处理polling状态,当收到消息时,就回调这个回调函数。

这个读线程的数据是从哪里来的呢,这就涉及到QMI service了。QMI service这部分代码就不是AP这边了,此份代码就在modem的adsp代码中了。

找时间再来续modem这边的adsp。

  1.  
  1.  

android 6.0 高通平台sensor 工作机制及流程(原创)的更多相关文章

  1. 高通平台sensor框架图【学习笔记】

  2. 高通平台msm8916修改开机logo【原创】

    经过两天的奋战终于把开机logo给搞定了啊. 首先修改开机logo要从哪里入手呢?先分析一下源码看看. ---> void display_image_on_screen() { struct ...

  3. 【转】高通平台android 环境配置编译及开发经验总结

    原文网址:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...

  4. 高通平台 lcd driver 调试小结

    一.概述 1.1 简介 本文档主要包括LCD模块的驱动流程分析.Framebuffer相关知识.Gralloc等相关内容,以及LCD调试的一些经验和相关bug的分析和讲解. 1.2  开发环境 And ...

  5. 高通平台的bootloader过程【转】

    ====================基本知识=======================LK是(L)ittle (K)ernel的缩写.高通平台android普遍采用LK作为其bootloade ...

  6. 高通平台Bootloader启动流程【转】

    本文转载自:http://blog.csdn.net/fang_first/article/details/49615631 ====================基本知识============= ...

  7. 高通平台msm8909 LK 实现LCD 兼容

    前段时间小米出现红米note2 换屏门,现在我们公司也要上演了:有两个供应商提供不同IC 的LCD panel. 软件区分的办法是读取LCD IC 的ID 寄存器,下面解析高通平台LK中LCD兼容的过 ...

  8. [修改高通平台WIFI MAC 地址] & [adb over wifi]

    [修改高通平台WIFI MAC 地址]fccmd --helpfccmd startfccmd getwifimacfccmd setwifimac 74:AC:5F:F5:D7:40 [adb ov ...

  9. 云计算分布式大数据Hadoop实战高手之路第七讲Hadoop图文训练课程:通过HDFS的心跳来测试replication具体的工作机制和流程

    这一讲主要深入使用HDFS命令行工具操作Hadoop分布式集群,主要是通过实验的配置hdfs-site.xml文件的心跳来测试replication具体的工作和流程. 通过HDFS的心跳来测试repl ...

随机推荐

  1. FastDFS 通过文件名获取文件信息

    /** * 获取文件信息 * * param string group_name 文件所在的组名 * param string file_id 文件id(如: M00/09/BE/rBBZolgj6O ...

  2. nginx服务器http重定向到https的正确写法

    http重定向到https使用了nginx的重定向命令.那么应该如何写重定向?之前老版本的nginx可能使用了以下类似的格式. rewrite ^/(.*)$ http://domain.com/$1 ...

  3. ThinkPhp 3.2 数据的连贯操作

    ThinkPHP模型基础类提供的连贯操作方法(也有些框架称之为链式操作),可以有效的提高数据存取的代码清晰度和开发效率,并且支持所有的CURD操作. 使用也比较简单, 假如我们现在要查询一个User表 ...

  4. sift特征源码

    先贴上我对Opencv3.1中sift源码的注释吧,虽然还有很多没看懂.先从detectAndCompute看起 void SIFT_Impl::detectAndCompute(InputArray ...

  5. Linux知识:/root/.bashrc与/etc/profile的异同

    Linux知识:/root/.bashrc与/etc/profile的异同 要搞清bashrc与profile的区别,首先要弄明白什么是交互式shell和非交互式shell,什么是login shel ...

  6. JavaScript停止冒泡和阻止浏览器默认行为

    JS停止冒泡 function myfn(e){ window.event? window.event.cancelBubble = true : e.stopPropagation(); } js阻 ...

  7. 碳膜电阻+1N5408二极管?

    整定电流: 整定: 调整, 确定, 是指某一物理量,到达某个一个设定值时, 设备开始动作. 主要是指电路中的一些起 保护作用的 继电器, 如: 电机, 控制电路中的 过电流继电器, 的整定值. 如空气 ...

  8. nginx+Memcached 缓存设计

    单页面缓存方案 单静态页缓存 解决问题场景 常见的缓存设计利用System.Web.Cache 保存在内存内,效率高,可以减轻数据库访问的压力.但是Web除了获取数据之外,还有呈现页面渲染,生成HTM ...

  9. c++ 接口和抽象类

    其实对抽象类与接口的区别一直是搞不太清楚,最近正在学习<设计模式>,期间用到了很多c++多态的知识.这是才恍然发现,是应该整理下这方面的知识了.但在翻阅书本.上网查阅资料之际,发现有篇文章 ...

  10. JDK,JRE,JVM,三者的区别于联系?

    万事开头难,从基础抓起! 下载JDK官网:http://www.oracle.com/technetwork/java/javase/downloads/index.html JDK:Java Dev ...