/************************************************************/ 分析背景: 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的運作流程即使如此。