程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 探秘SensorHAL

探秘SensorHAL

編輯:C++入門知識

/************************************************************/   分析背景: Android4.1.2(Based on CyanogenMod 10) DASH(https://github.com/sonyxperiadev/DASH)   1.接口頭文件sensors.h(hardware/libhardware/include/sensors.h)     剛一打開就看到SENSOR HAL的ID 為"SENSORS_HARDWARE_MODULE_ID"。 [cpp]   /**   * Handles must be higher than SENSORS_HANDLE_BASE and must be unique.   * A Handle identifies a given sensors. The handle is used to activate   * and/or deactivate sensors.   * In this version of the API there can only be 256 handles.   */   #define SENSORS_HANDLE_BASE             0   #define SENSORS_HANDLE_BITS             8   #define SENSORS_HANDLE_COUNT            (1<<SENSORS_HANDLE_BITS)   /* 8位能夠支持256個handle */      /**   * 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  //距離傳感器   [cpp]   #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  //環境溫度傳感器         支持的傳感器還很多,但是 一般設備並不會用到這麼多傳感器,也就是加速度傳感器、重力傳感器、方向傳感器、距離傳感器、光線傳感器這些,陀螺儀都很少見。 [cpp]   /**    * Definition of the axis    * ----------------------    *    * This API is relative to the screen of the device in its default orientation,    * that is, if the device can be used in portrait or landscape, this API    * is only relative to the NATURAL orientation of the screen. In other words,    * the axis are not swapped when the device's screen orientation changes.    * Higher level services /may/ perform this transformation.    *    *   x<0         x>0    *                ^    *                |    *    +-----------+-->  y>0    *    |           |    *    |           |    *    |    設備    |    *    |           |   / z<0    *    |  面朝天空  |  /    *    |           | /    *    O-----------+/    *    |[]  [ ]  []/    *    +----------/+     y<0    *              /    *             /    *           |/ z>0 (toward the sky)    *    *    O: Origin (x=0,y=0,z=0)     還用有趣的符號圖形形象的描述了“軸”的概念。然後就是一坨坨的傳感器知識,blablabla......   定義了幾個結構體: 1) sensors_vec_t 對單個傳感器的泛用性封裝,包含坐標、角度、狀態等信息; 2) sensors_event_t 對傳感器細致的數據再封裝,包含版本號、傳感器類型、數據、加速度、磁力、角度、重力等等等等的信息; 3) sensor_t 對應每個傳感器,是都會有的數據,包括傳感器名稱、版本、handle句柄、類型、最大范圍、解析度、耗能、最小延遲等信息; 4) sensors_module_t 對hw_module_t的擴展,不僅有common為hw_module_t,還定義了一個函數get_sensors_list用來獲取所支持的傳感器,返回值為傳感器總數; 5) sensors_poll_device_t 每個傳感器所私有的數據操作,包括(反)激活、設置延時、提取數據等動作。   最後定義了兩個API函數用來打開/關閉一個傳感器。 [cpp]  static inline int sensors_open(const struct hw_module_t* module,           struct sensors_poll_device_t** device) {       return module->methods->open(module,               SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);   }      static inline int sensors_close(struct sensors_poll_device_t* device) {       return device->common.close(&device->common);   }     2. 服務開啟之路(1) sensor服務由system_server開啟: frameworks/base/cmds/system_server/system_init.cpp [cpp]   extern "C" status_t system_init()   {       ALOGI("Entered system_init()");          sp<ProcessState> proc(ProcessState::self());          sp<IServiceManager> sm = defaultServiceManager();       ALOGI("ServiceManager: %p\n", sm.get());       ...       }          property_get("system_init.startsensorservice", propBuf, "1");       if (strcmp(propBuf, "1") == 0) {           // Start the sensor service           SensorService::instantiate();       }   ...   }   調用到frameworks/base/services/sensorservice/SensorService.cpp [cpp]   void SensorService::onFirstRef()   {       ALOGD("nuSensorService starting...");          SensorDevice& dev(SensorDevice::getInstance());   之後又調用到了SensorDevice.cpp(同目錄下) [cpp]   SensorDevice::SensorDevice()       :  mSensorDevice(0),          mSensorModule(0)   {       status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,               (hw_module_t const**)&mSensorModule);          ALOGE_IF(err, "couldn't load %s module (%s)",               SENSORS_HARDWARE_MODULE_ID, strerror(-err));          if (mSensorModule) {           err = sensors_open(&mSensorModule->common, &mSensorDevice);              ALOGE_IF(err, "couldn't open device for module %s (%s)",                   SENSORS_HARDWARE_MODULE_ID, strerror(-err));              if (mSensorDevice) {               sensor_t const* list;               ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);                  mActivationCount.setCapacity(count);               Info model;               for (size_t i=0 ; i<size_t(count) ; i++) {                   mActivationCount.add(list[i].handle, model);                   mSensorDevice->activate(mSensorDevice, list[i].handle, 0);               }           }       }   }     這段負責打開HAL,取得需要的數據及handle,對應的部分在HAL的代碼中,見DASH/sensors_module.c [cpp]  struct sensors_module_t HAL_MODULE_INFO_SYM = {       common: {           tag: HARDWARE_MODULE_TAG,           version_major: 1,           version_minor: 0,           id: SENSORS_HARDWARE_MODULE_ID,           name : "dash",           author : "[email protected]",           methods: &sensors_module_methods,       },       get_sensors_list: sensors_list_get   };     ID對上了,即可以成功打開,mSensorModule變得有效了。 然後SensorDevice.cpp調用API sensors_open,這個函數在接口頭文件中有定義: [cpp]   static inline int sensors_open(const struct hw_module_t* module,           struct sensors_poll_device_t** device) {       return module->methods->open(module,               SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);   }     是開調用HAL的open方法: [cpp]  static int sensors_module_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device)   {       struct sensors_poll_device_t *dev;             if (strcmp(id, SENSORS_HARDWARE_POLL))           return 0;             dev = malloc(sizeof(*dev));       if (!dev)           return -1;             memset(dev, 0, sizeof(*dev));       dev->common.tag = HARDWARE_DEVICE_TAG;       dev->common.version = 0;       dev->common.module = (struct hw_module_t*)module;       dev->common.close = sensors_module_close;       dev->activate = sensors_module_activate;       dev->setDelay = sensors_module_set_delay;       dev->poll = sensors_module_poll;             *device = (struct hw_device_t*) dev;             sensors_config_read(NULL);       sensors_fifo_init();       sensors_list_foreach_api(sensors_init_iterator, NULL);             return 0;   }         struct hw_module_methods_t sensors_module_methods = {       open: sensors_module_open   };     實際調用到了sensors_module_open,此函數返回0代表成功,-1代表打開失敗,主要工作是組裝device,最終將句柄交給mSensorDevice,即: [cpp]   mSensorDevice->common.tag = HARDWARE_DEVICE_TAG;   mSensorDevice->common.version = 0;   mSensorDevice->common.module = (struct hw_module_t*)module;   mSensorDevice->common.close = sensors_module_close;   mSensorDevice->activate = sensors_module_activate;   mSensorDevice->setDelay = sensors_module_set_delay;   mSensorDevice->poll = sensors_module_poll;     之前在說明接口頭文件時,說明了,對於傳感器的數據操作有三個重要函數就是avtivate, setDelay, poll。記住這幾個函數,稍後做分析。 在mSensorDevice成功被組裝後,調用sensors_module_t自創的另一重要接口:get_sensors_list。瞧一瞧此函數在本實例中的具體實現(DASH/sensors_list.c): [cpp]   static struct sensor_t sensors[DASH_MAX_SENSORS];   static struct sensor_api_t* sensor_apis[DASH_MAX_SENSORS];   static int number_of_sensors = 0;   [cpp] view plaincopyprint? int sensors_list_get(struct sensors_module_t* module, struct sensor_t const** plist)   {       *plist = sensors;       return number_of_sensors;   }     此函數完成兩個工作,一將傳感器列表賦給指針plist,二返回傳感器數量。這裡sensors列表和number_of_sensors是如何運作的: [cpp]   int sensors_list_register(struct sensor_t* sensor, struct sensor_api_t* api)   {       if (!sensor || !api)           return -1;             if (number_of_sensors > DASH_MAX_SENSORS-1)           return -1;             sensor_apis[number_of_sensors] = api;       /* We have to copy due to sensor API */       memcpy(&sensors[number_of_sensors++], sensor, sizeof(*sensor));             return 0;   }     每個傳感器都會調用sensors_list_register將自己注冊進sensors列表中,並且會將自己的API也注冊進sensors_apis列表中,來一個例子吧(DASH/sensors/bma150_input.c): [cpp]   struct sensor_desc {       struct sensors_select_t select_worker;       struct sensor_t sensor;       struct sensor_api_t api;          int input_fd;       float current_data[3];          char *rate_path;          /* config options */       int axis_x;       int axis_y;       int axis_z;          int neg_x;       int neg_y;       int neg_z;       int64_t  delay_requests[MAX_CLIENTS];   };      static struct sensor_desc bma150_input = {       .sensor = {           name: "BMA150 accelerometer",           vendor: "Bosch Sensortec GmbH",           version: sizeof(sensors_event_t),           handle: SENSOR_ACCELEROMETER_HANDLE,           type: SENSOR_TYPE_ACCELEROMETER,           maxRange: 9.81,           resolution: 20,           power: 0.13,           minDelay: 5000       },       .api = {           init: bma150_input_init,           activate: bma150_input_activate,           set_delay: bma150_input_fw_delay,           close: bma150_input_close       },       .input_fd = -1,       .axis_x = 0,       .axis_y = 1,       .axis_z = 2,       .neg_x = 0,       .neg_y = 0,       .neg_z = 0   };   以上是BMA150注冊了屬於自己的初始化、激活、延遲、關閉等操作。 每次注冊完成後自會對number_of_sensors進行+1操作。這樣所有的傳感器注冊完成後,就會形成兩個列表和一個傳感器總數。sensors_list_get也就理解了。 在獲取到總數後,會根據總數進行循環遍歷,挨個激活傳感器。 [cpp]  for (size_t i=0 ; i<size_t(count) ; i++) {                   mActivationCount.add(list[i].handle, model);                   mSensorDevice->activate(mSensorDevice, list[i].handle, 0);               }     OK,這下,引出了三大數據處理函數之一:activate。 sensors_module.c [cpp]   /* mSensorDevice->activate = sensors_module_activate; */   static int sensors_module_activate(struct sensors_poll_device_t *dev,                      int handle, int enabled)   {       struct sensor_api_t* api = sensors_list_get_api_from_handle(handle);             if (!api) {           ALOGE("%s: unable to find handle!", __func__);                   return -1;           }             if (api->activate(api, enabled) < 0)           return -1;             return 0;   }     sensors_list.c [cpp]   struct sensor_api_t* sensors_list_get_api_from_handle(int handle)   {       int i;       for (i = 0; i < number_of_sensors; i++)           if (sensors[i].handle == handle)               return sensor_apis[i];       return NULL;   }     比如BMA150的handle就是SENSOR_ACCELEROMETER_HANDLE,通過簡單的匹配後,就能找到對應的sensors_api[x],然後執行active也就是bma150_input_activate函數,有興趣就簡單看一下代碼,大體意思就是打開驅動獲取句柄,然後組裝給相關參數。   至此SensorDevice的大體工作也就完成了,總結就是成功獲取HAL後,對每個傳感器執行activate操作。   3.服務開啟之路(2) 之所分(1)(2)是覺得SensorDevice部分可以單獨成一部分,畢竟多數是在跟HAL在交互,這部分將分析完服務部分。 回頭看SensorService::onFirstRef() [cpp]   void SensorService::onFirstRef()   {       ALOGD("nuSensorService starting...");          SensorDevice& dev(SensorDevice::getInstance());          if (dev.initCheck() == NO_ERROR) {      /**********************************  檢測SensorDevice執行是否成功,所獲取的數據是否有效。  >status_t SensorDevice::initCheck() const {      return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;  }  **********************************/           sensor_t const* list;           ssize_t count = dev.getSensorList(&list);   /* 執行與(1)中sensors_list_get一樣的工作 */           if (count > 0) {               ssize_t orientationIndex = -1;               bool hasGyro = false;               uint32_t virtualSensorsNeeds =                       (1<<SENSOR_TYPE_GRAVITY) |                       (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |                       (1<<SENSOR_TYPE_ROTATION_VECTOR);                  mLastEventSeen.setCapacity(count);               for (ssize_t i=0 ; i<count ; i++) {                   registerSensor( new HardwareSensor(list[i]) );                   switch (list[i].type) {                       case SENSOR_TYPE_ORIENTATION:                           orientationIndex = i;                           break;                       case SENSOR_TYPE_GYROSCOPE:                           hasGyro = true;                           break;                       case SENSOR_TYPE_GRAVITY:                       case SENSOR_TYPE_LINEAR_ACCELERATION:                       case SENSOR_TYPE_ROTATION_VECTOR:                           virtualSensorsNeeds &= ~(1<<list[i].type);                           break;                   }               }   /* 遍歷查看SENSOR HAL都支持哪些類型的傳感器 */                  // it's safe to instantiate the SensorFusion object here               // (it wants to be instantiated after h/w sensors have been               // registered)               const SensorFusion& fusion(SensorFusion::getInstance());                  if (hasGyro) {                   // Always instantiate Android's virtual sensors. Since they are                   // instantiated behind sensors from the HAL, they won't                   // interfere with applications, unless they looks specifically                   // for them (by name).                      registerVirtualSensor( new RotationVectorSensor() );                   registerVirtualSensor( new GravitySensor(list, count) );                   registerVirtualSensor( new LinearAccelerationSensor(list, count) );                      // these are optional                   registerVirtualSensor( new OrientationSensor() );                   registerVirtualSensor( new CorrectedGyroSensor(list, count) );                      // virtual debugging sensors...                   char value[PROPERTY_VALUE_MAX];                   property_get("debug.sensors", value, "0");                   if (atoi(value)) {                       registerVirtualSensor( new GyroDriftSensor() );                   }               } else if (orientationIndex != -1) {                   // If we don't have a gyro but have a orientation sensor from                   // elsewhere, we can compute rotation vector from that.                   // (Google Maps expects rotation vector sensor to exist.)                      registerVirtualSensor( &RotationVectorSensor2::getInstance() );               }                  // build the sensor list returned to users               mUserSensorList = mSensorList;               if (hasGyro &&                       (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {                   // if we have the fancy sensor fusion, and it's not provided by the                   // HAL, use our own (fused) orientation sensor by removing the                   // HAL supplied one form the user list.                   if (orientationIndex >= 0) {                       mUserSensorList.removeItemsAt(orientationIndex);                   }               }                  run("SensorService", PRIORITY_URGENT_DISPLAY);               mInitCheck = NO_ERROR;           }       }   }     從上面可以看出,如果傳感器中有SENSOR_TYPE_GYROSCOPE類型的話,也就是陀螺儀(高端傳感器),會定義hasGyro,從而注冊多個虛擬傳感器,blablabla…… 最後會觸發一個重要動作:run。 回頭查看SensorService類的定義: [cpp]   class SensorService :           public BinderService<SensorService>,           public BnSensorServer,           protected Thread     發現SensorService是繼承了Thread的。 那麼run的工作實際是啟動了線程,threadLoop: [cpp]   bool SensorService::threadLoop()   {       ALOGD("nuSensorService thread starting...");          const size_t numEventMax = 16;       const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size();       sensors_event_t buffer[minBufferSize];       sensors_event_t scratch[minBufferSize];       SensorDevice& device(SensorDevice::getInstance());       const size_t vcount = mVirtualSensorList.size();          ssize_t count;       do {           count = device.poll(buffer, numEventMax);           if (count<0) {               ALOGE("sensor poll failed (%s)", strerror(-count));               break;           }      ...   }     發現這個線程會一直執行poll操作,這個操作是什麼呢?還記得“服務開啟之路(1)”中提到的嗎? [cpp]   mSensorDevice->poll = sensors_module_poll;   是在HAL中的函數,最終指向sensors_module_poll ( DASH/sensors_module.c ) [cpp]  static int sensors_module_poll(struct sensors_poll_device_t *dev,                      sensors_event_t* data, int count)   {       int ret;          while ((ret = sensors_fifo_get_all(data, count)) == 0)           ;          return ret;   }     ( DASH/sensors_fifo.c ) [cpp]  void sensors_fifo_put(sensors_event_t *data)   {       pthread_mutex_lock(&sensors_fifo.mutex);          if (sensors_fifo.fifo_i < FIFO_LEN)           sensors_fifo.fifo[sensors_fifo.fifo_i++] = *data;          pthread_cond_broadcast(&sensors_fifo.data_cond);       pthread_mutex_unlock(&sensors_fifo.mutex);   }      int sensors_fifo_get_all(sensors_event_t *data, int len)   {       int i;          /* This function deliberately drops all packets above len. */       pthread_mutex_lock(&sensors_fifo.mutex);       pthread_cond_wait(&sensors_fifo.data_cond, &sensors_fifo.mutex);          for (i = 0; (i < sensors_fifo.fifo_i) && (i < len); i++)           data[i] = sensors_fifo.fifo[i];       sensors_fifo.fifo_i = 0;       pthread_mutex_unlock(&sensors_fifo.mutex);          return i;   }     上邊的函數用到了線程等待,有興趣的可以去百度,很好理解,就是兩個線程等待一個變量data_cond,sensors_fifo_put在放置完data後會釋放掉data_cond,而sensors_fifo_get_all在data_cond釋放之前會一直進行等待。 繼續向前跟蹤sensors_fifo_put ( DASH/sensors/bma150_input.c ): [cpp]   static void *bma150_input_read(void *arg)   {       struct sensor_api_t *s = arg;       struct sensor_desc *d = container_of(s, struct sensor_desc, api);       struct input_event event;       int fd = d->select_worker.get_fd(&d->select_worker);       sensors_event_t data;          memset(&data, 0, sizeof(data));       while (read(fd, &event, sizeof(event)) > 0) {           switch (event.type) {           case EV_ABS:               switch (event.code) {               case ABS_X:                   d->current_data[0] = ev2grav(event.value);                   break;                  case ABS_Y:                   d->current_data[1] = ev2grav(event.value);                   break;                  case ABS_Z:                   d->current_data[2] = ev2grav(event.value);                   break;                  case ABS_MISC:               default:                   break;               }               break;              case EV_SYN:                  data.acceleration.x = (d->neg_x ? -d->current_data[d->axis_x] :                                  d->current_data[d->axis_x]);               data.acceleration.y = (d->neg_y ? -d->current_data[d->axis_y] :                                  d->current_data[d->axis_y]);               data.acceleration.z = (d->neg_z ? -d->current_data[d->axis_z] :                                  d->current_data[d->axis_z]);               data.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;                  data.sensor = bma150_input.sensor.handle;               data.type = bma150_input.sensor.type;               data.version = bma150_input.sensor.version;               data.timestamp = get_current_nano_time();                  sensors_fifo_put(&data);                  goto exit;              default:               goto exit;           }       }      exit:       return NULL;   }     上述函數很好理解,首先取得此傳感器的內核驅動句柄,然後等待此句柄輸出信息,當取得信息後,對信息進行解析與再封裝,最終寫入到data中。那麼bma150_input_read又是誰來調用呢?答案在此傳感器的初始化過程中: [cpp]   static int bma150_input_init(struct sensor_api_t *s)   {       struct sensor_desc *d = container_of(s, struct sensor_desc, api);       int fd;       bma150_input_read_config(d);          /* check for availablity */       fd = open_input_dev_by_name(BMA150_INPUT_NAME, O_RDONLY | O_NONBLOCK);       if (fd < 0) {           ALOGE("%s: unable to find %s input device!\n", __func__,               BMA150_INPUT_NAME);           return -1;       }       d->rate_path = bma150_get_rate_path(fd);       close(fd);          sensors_select_init(&d->select_worker, bma150_input_read, s, -1);       return 0;   }   可能現在會有迷惑,這個bma150_input_init是什麼時候啟動的呢?這是問題1,問題2是sensors_select_init是怎麼吧bma150_input_read啟動起來的?   下面一次解決,問題1: [cpp]   static struct sensor_desc bma150_input = {   ...       .api = {           init: bma150_input_init,           activate: bma150_input_activate,           set_delay: bma150_input_fw_delay,           close: bma150_input_close       },   ...   };   bma150_input_init被注冊到api->init. ( DASH/sensors_module.c ) [cpp]   static int sensors_module_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device)   {       ...       sensors_list_foreach_api(sensors_init_iterator, NULL);          return 0;   }      static int sensors_init_iterator(struct sensor_api_t* api, void *arg)   {       return api->init(api);   }     ( DASH/sensors_list.c ) [cpp]  void sensors_list_foreach_api(int (*f)(struct sensor_api_t* api, void* arg),                     void *arg)   {       int i;       for (i = 0; i < number_of_sensors; i++)           if (f(sensor_apis[i], arg) != SENSOR_OK) {               sensors_list_deregister(sensor_apis[i]);               /* need to revisit this position after deregister */               --i;           }   }   遍歷所有注冊過的傳感器,執行其api->init. 問題1解決完畢。   問題2: ( DASH/sensors_select.c ) [cpp]  void sensors_select_init(struct sensors_select_t* s,               void* (*select_func)(void *arg), void* arg, int fd)   {       s->suspend = sensors_select_suspend;       s->resume = sensors_select_resume;       s->destroy = sensors_select_destroy;       s->set_delay = sensors_select_set_delay;       s->set_fd = sensors_select_set_fd;       s->get_fd = sensors_select_get_fd;       s->select_callback = select_func;       s->arg = arg;       s->fd = fd;       s->delay = 0;              if (pipe(s->ctl_fds) < 0)           ALOGE("%s: pipe failed: %s", __func__, strerror(errno));          sensors_worker_init(&s->worker, sensors_select_callback, s);       s->worker.set_delay(&s->worker, 0);       pthread_mutex_init(&s->fd_mutex, NULL);   }     bma150_init_read為該函數的第二個參數,即select_func, 組裝給了s->select_callback。送去sensors_worker_init函數( DASH/sensors_worker.c ): [cpp]   void sensors_worker_init(struct sensors_worker_t* worker,               void* (*work_func)(void *arg), void* arg)   {       worker->mode = SENSOR_SLEEP;          worker->poll_callback = work_func;       worker->suspend = sensors_worker_suspend;       worker->resume = sensors_worker_resume;       worker->destroy = sensors_worker_destroy;       worker->set_delay = sensors_worker_set_delay;       worker->delay_ns = 200000000L;       worker->arg = arg;          pthread_mutex_init (&worker->mode_mutex, NULL);       pthread_cond_init (&worker->suspend_cond, NULL);       pthread_create(&worker->worker_thread_id, NULL,                  sensors_worker_internal_worker, (void*) worker);   }     該函數第二個參數為sensors_select_init所送入的sensors_select_callback, 暫放此處,稍後分析,只記得他化身work_func組裝給了worker->poll_callback, 最終被當作參數送入新開啟的線程sensors_worker_internal_worker中: [cpp]   static void *sensors_worker_internal_worker(void *arg)   {       struct sensors_worker_t* worker = (struct sensors_worker_t*) arg;       enum sensors_worker_mode mode;          while (1) {           pthread_mutex_lock(&worker->mode_mutex);           mode = worker->mode;           pthread_mutex_unlock(&worker->mode_mutex);              switch (mode) {           case SENSOR_DESTROY:               goto exit;              case SENSOR_SLEEP:               pthread_mutex_lock(&worker->mode_mutex);               pthread_cond_wait(&worker->suspend_cond, &worker->mode_mutex);               pthread_mutex_unlock(&worker->mode_mutex);               break;              default:               worker->poll_callback(worker->arg);               break;           }           if (worker->delay_ns)               sensor_nano_sleep(worker->delay_ns);       }   exit:       return NULL;   }     這是一個工作線程,用來處理不同模式的不同動作,這些不同的模式由worker->mode來進行控制,同時worker->mode又由互斥鎖worker->mode_mutex進行保護來防止讀寫沖突。此mode實際有三種: SENSOR_SLEEP SENSOR_RUNNING SENSOR_DESTROY 分別對應三個工作函數: sensors_worker_suspend sensors_worker_resume sensors_worker_destroy 這三個工作函數又在sensors_worker_init初始化時分別分配給了: worker->suspend worker->resume worker->destroy 綜上, sensors_worker_internal_worker中default即為SENSOR_RUNNING,其他狀態暫不說明,先解決了這個RUNNING。在第一次初始化的時候默認給出的是SLEEP狀態,則會等待suspend_cond變量,試看誰在使用這個變量。在sensors_worker.c中不難發現,在resume和destroy函數中,當前一狀態為SLEEP時,會釋放suspend_cond: [cpp]   static void sensors_worker_resume(struct sensors_worker_t* worker)   {       enum sensors_worker_mode prev_mode;          pthread_mutex_lock(&worker->mode_mutex);       prev_mode = worker->mode;       worker->mode = SENSOR_RUNNING;          if (prev_mode == SENSOR_SLEEP)           pthread_cond_broadcast(&worker->suspend_cond);          pthread_mutex_unlock(&worker->mode_mutex);   }      static void sensors_worker_destroy(struct sensors_worker_t* worker)   {       enum sensors_worker_mode prev_mode;          pthread_mutex_lock(&worker->mode_mutex);       prev_mode = worker->mode;       worker->mode = SENSOR_DESTROY;          if (prev_mode == SENSOR_SLEEP)           pthread_cond_broadcast(&worker->suspend_cond);          pthread_mutex_unlock(&worker->mode_mutex);       pthread_join(worker->worker_thread_id, NULL);   }     兩者不同之處在於,resume會讓傳感器的狀態切換到RUNNING,而destroy會使其切換至DESTROY狀態,從而導致線程sensors_worker_internal_worker退出,傳感器工作停止。問題又來了,初始化的狀態是SLEEP,什麼時候?誰?來激活這個工作線程呢?問題的答案在bma150_input.c ( DASH/bma150_input.c ): [cpp]   static int bma150_input_activate(struct sensor_api_t *s, int enable)   {       struct sensor_desc *d = container_of(s, struct sensor_desc, api);       int fd = d->select_worker.get_fd(&d->select_worker);          /* suspend/resume will be handled in kernel-space */       if (enable && (fd < 0)) {           fd = open_input_dev_by_name(BMA150_INPUT_NAME,               O_RDONLY | O_NONBLOCK);           if (fd < 0) {               ALOGE("%s: failed to open input dev %s\n", __func__,                   BMA150_INPUT_NAME);               return -1;           }           d->select_worker.set_fd(&d->select_worker, fd);           d->select_worker.resume(&d->select_worker);       } else if (!enable && (fd > 0)) {           d->select_worker.set_fd(&d->select_worker, -1);           d->select_worker.suspend(&d->select_worker);       }          return 0;   }     前面只是一代而過activate函數,沒有進行分析,回頭來看,原來resume與suspend操作就在這裡,當未初始化且要求開啟時,尋找驅動句柄,並設置句柄,然後執行resume操作,從而使sensors_worker_internal_worker工作線程開啟,執行worker->poll_callback函數。在回去之前還是把avtivate看完,除了上邊說的開啟的情況,就是關閉的情況。當驅動句柄有效,且要求關閉時,設置句柄為-1(無效),並執行suspend操作,使傳感器進入SLEEP狀態,繼續等待suspend_cond變量。 在執行poll_callback時候一層層向回摸吧,worker->arg就等於sensors_worker_init所帶入的arg。 worker->poll_back = (work_func); (work_func) = sensors_select_callback; ( DASH/sensors_select.c ) [cpp]   static void *sensors_select_callback(void *arg)   {       fd_set readfds;       int ret;       struct sensors_select_t *s = arg;       int maxfd;          LOCK(&s->fd_mutex);       maxfd = s->ctl_fds[0] > s->fd ? s->ctl_fds[0] : s->fd;       FD_ZERO(&readfds);       FD_SET(s->ctl_fds[0], &readfds);       FD_SET(s->fd, &readfds);       UNLOCK(&s->fd_mutex);       ret = select(maxfd + 1, &readfds, NULL, NULL, NULL);          if (ret < 0) {           ALOGE("%s: select failed!\n", __func__);       } else if (ret) {           if (FD_ISSET(s->ctl_fds[0], &readfds)) {               read(s->ctl_fds[0], &ret, sizeof(ret));           } else if (FD_ISSET(s->fd, &readfds)) {               LOCK(&wrapper_mutex);               LOCK(&s->fd_mutex);               if (s->fd >= 0)                   s->select_callback(s->arg);               UNLOCK(&s->fd_mutex);               UNLOCK(&wrapper_mutex);           }       }       return NULL;   }     一層層的設置執行,最終執行到s->select_callback,參數為s->arg。 select_callback = (select_func);www.2cto.com (select_func) = bma150_input_read; 終於執行到了這一步,問題2解決。 總結: 一切的一切始於SensorService的threadLoop,他執行了一個poll操作,從而層層調用到SensorHAL,HAL經過初始化及激活後,開啟了一個工作線程。當工作線程處於RUNNING(default)狀態時,會無限循環來讀取硬件驅動句柄所發出的數據,然後經過解析重構發回到SensorService中。至此,服務成功開啟,從驅動中源源不斷的獲取數據。這個SensorService的threadLoop工作還有很多,大體概括就是對獲取到的驅動數據進行分類,處理,最後發送……blablabla,這裡邊涉及到很多專業知識,也就不便再進行分析。總之SensorHAL的運作流程即使如此。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved