Android sensorservice
来源:互联网 发布:淘宝自刷平台 编辑:程序博客网 时间:2024/05/20 18:50
private void startBootstrapServices() { ... startSensorService(); }
startsensorService是一个native函数,其具体实现在com_android_server_SystemServer.cpp的android_server_SystemServer_startSensorService函数中。
static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) { char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the sensor service SensorService::instantiate(); }}
SensorService::instantiate()的instantiate函数定义在BinderService.h中,目的在于向ServiceManager注册SensorService组件。
static void instantiate() { publish(); }
static status_t publish(bool allowIsolated = false) { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); }onFirstRef函数来自RefBase,在第一次被强指针引用时调用。
void SensorService::onFirstRef(){ ALOGD("nuSensorService starting..."); SensorDevice& dev(SensorDevice::getInstance()); if (dev.initCheck() == NO_ERROR) { sensor_t const* list; ssize_t count = dev.getSensorList(&list); if (count > 0) { ssize_t orientationIndex = -1; bool hasGyro = false, hasAccel = false, hasMag = 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_ACCELEROMETER: hasAccel = true; break; case SENSOR_TYPE_MAGNETIC_FIELD: hasMag = true; break; case SENSOR_TYPE_ORIENTATION: orientationIndex = i; break; case SENSOR_TYPE_GYROSCOPE: case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: hasGyro = true; break; case SENSOR_TYPE_GRAVITY: case SENSOR_TYPE_LINEAR_ACCELERATION: case SENSOR_TYPE_ROTATION_VECTOR: virtualSensorsNeeds &= ~(1<<list[i].type); break; } } // 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()); // build the sensor list returned to users mUserSensorList = mSensorList; if (hasGyro && hasAccel && hasMag) { Sensor aSensor; // Add Android virtual sensors if they're not already // available in the HAL aSensor = registerVirtualSensor( new RotationVectorSensor() ); if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) { mUserSensorList.add(aSensor); } aSensor = registerVirtualSensor( new GravitySensor(list, count) ); if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) { mUserSensorList.add(aSensor); } aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) ); if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) { mUserSensorList.add(aSensor); } aSensor = registerVirtualSensor( new OrientationSensor() ); if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) { // if we are doing our own rotation-vector, also add // the orientation sensor and remove the HAL provided one. mUserSensorList.replaceAt(aSensor, orientationIndex); } // virtual debugging sensors are not added to mUserSensorList registerVirtualSensor( new CorrectedGyroSensor(list, count) ); registerVirtualSensor( new GyroDriftSensor() ); } // debugging sensor list mUserSensorListDebug = mSensorList; // Check if the device really supports batching by looking at the FIFO event // counts for each sensor. bool batchingSupported = false; for (size_t i = 0; i < mSensorList.size(); ++i) { if (mSensorList[i].getFifoMaxEventCount() > 0) { batchingSupported = true; break; } } if (batchingSupported) { // Increase socket buffer size to a max of 100 KB for batching capabilities. mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED; } else { mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED; } // Compare the socketBufferSize value against the system limits and limit // it to maxSystemSocketBufferSize if necessary. FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r"); char line[128]; if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) { line[sizeof(line) - 1] = '\0'; size_t maxSystemSocketBufferSize; sscanf(line, "%zu", &maxSystemSocketBufferSize); if (mSocketBufferSize > maxSystemSocketBufferSize) { mSocketBufferSize = maxSystemSocketBufferSize; } } if (fp) { fclose(fp); } mWakeLockAcquired = false; mLooper = new Looper(false); const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT; mSensorEventBuffer = new sensors_event_t[minBufferSize]; mSensorEventScratch = new sensors_event_t[minBufferSize]; mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize]; mCurrentOperatingMode = NORMAL; mNextSensorRegIndex = 0; for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) { mLastNSensorRegistrations.push(); } mInitCheck = NO_ERROR; mAckReceiver = new SensorEventAckReceiver(this); mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); run("SensorService", PRIORITY_URGENT_DISPLAY); } }}
首先获得一个SensorDevice单例对象,先看看SensorDevice的默认构造函数:
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_1(&mSensorModule->common, &mSensorDevice); ALOGE_IF(err, "couldn't open device for module %s (%s)", SENSORS_HARDWARE_MODULE_ID, strerror(-err)); if (mSensorDevice) { if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 || mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) { ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3"); } 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( reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), list[i].handle, 0); } } }}
谷歌为Sensor提供了统一的HAL接口,方便厂商根据该接口完成具体的硬件抽象层,接口文件在/hardware/libhardware/include/hardware/Sensors.h中。首先将
sensors_poll_device_1*类型的mSensorDevice和sensors_module_t*类型的mSensorModule成员变量设为0,这两个类型定义在Sensor.h中。sensors_module_t类型是对
hw_module_t类型的封装外加一个get_sensors_list函数。sensors_poll_device_l是对hw_device_t类型的封装外加poll(多路监听方法),activate(设备激活方法)和
setDelay(设备延迟方法)。hw_get_module是jni层获取HAL层module的接口函数,原型为hareware.c中的:int hw_get_module(const char *id, const struct
hw_module_t **module),第一个参数为硬件模块的id,第二个参数指向硬件模块对应的hw_module_t结构体地址(symbol地址)。
typedef struct sensors_poll_device_1 { union { /* sensors_poll_device_1 is compatible with sensors_poll_device_t, * and can be down-cast to it */ struct sensors_poll_device_t v0; struct { struct hw_device_t common; /* Activate/de-activate one sensor. Return 0 on success, negative * * sensor_handle is the handle of the sensor to change. * enabled set to 1 to enable, or 0 to disable the sensor. * * Return 0 on success, negative errno code otherwise. */ int (*activate)(struct sensors_poll_device_t *dev, int sensor_handle, int enabled); /** * Set the events's period in nanoseconds for a given sensor. * If sampling_period_ns > max_delay it will be truncated to * max_delay and if sampling_period_ns < min_delay it will be * replaced by min_delay. */ int (*setDelay)(struct sensors_poll_device_t *dev, int sensor_handle, int64_t sampling_period_ns); /** * Returns an array of sensor data. */ int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int count); };
struct sensors_module_t { struct hw_module_t common; /** * Enumerate all available sensors. The list is returned in "list". * @return number of sensors in the list */ int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t const** list); /** * Place the module in a specific mode. The following modes are defined * * 0 - Normal operation. Default state of the module. * 1 - Loopback mode. Data is injected for the the supported * sensors by the sensor service in this mode. * @return 0 on success * -EINVAL if requested mode is not supported * -EPERM if operation is not allowed */ int (*set_operation_mode)(unsigned int mode);};
int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}
int hw_get_module_by_class(const char *class_id, const char *inst, const struct hw_module_t **module){ int i = 0; char prop[PATH_MAX] = {0}; char path[PATH_MAX] = {0}; char name[PATH_MAX] = {0}; char prop_name[PATH_MAX] = {0}; if (inst) snprintf(name, PATH_MAX, "%s.%s", class_id, inst); else strlcpy(name, class_id, PATH_MAX);//class_id拷贝到name /* * Here we rely on the fact that calling dlopen multiple times on * the same .so will simply increment a refcount (and not load * a new copy of the library). * We also assume that dlopen() is thread-safe. */ /* First try a property specific to the class and possibly instance */ snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);//prop为ro.hardware.(name) if (property_get(prop_name, prop, NULL) > 0) {//获取prop_name的属性值,保存在prop中 if (hw_module_exists(path, sizeof(path), name, prop) == 0) {//path为/system/lib/hw/(name).(prop).so或者/vendor/lib/hw/(name).(prop).so{ goto found; } } /* Loop through the configuration variants looking for a module */ for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } if (hw_module_exists(path, sizeof(path), name, prop) == 0) { goto found; } } /* Nothing found, try the default */ if (hw_module_exists(path, sizeof(path), name, "default") == 0) { goto found; } return -ENOENT;found: /* load the module, if this fails, we're doomed, and we should not try * to load a different variant. */ return load(class_id, path, module);}
编译好的模块文件位于out/target/product/generic/system/lib/hw(对应设备上的/system/lib/hw;/vendor/lib/hw保存设备厂商提供的HAL层模块接口文件。hw_module_exists
函数作用在于检查HAL模块接口文件是否存在。
static int load(const char *id, const char *path, const struct hw_module_t **pHmi){ int status = -EINVAL; void *handle = NULL; struct hw_module_t *hmi = NULL; /* * load the symbols resolving undefined symbols before * dlopen returns. Since RTLD_GLOBAL is not or'd in with * RTLD_NOW the external symbols will not be global */ handle = dlopen(path, RTLD_NOW); if (handle == NULL) { char const *err_str = dlerror(); ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown"); status = -EINVAL; goto done; } /* Get the address of the struct hal_module_info. */ const char *sym = HAL_MODULE_INFO_SYM_AS_STR; hmi = (struct hw_module_t *)dlsym(handle, sym); if (hmi == NULL) { ALOGE("load: couldn't find symbol %s", sym); status = -EINVAL; goto done; } /* Check that the id matches */ if (strcmp(id, hmi->id) != 0) { ALOGE("load: id=%s != hmi->id=%s", id, hmi->id); status = -EINVAL; goto done; } hmi->dso = handle; /* success */ status = 0; done: if (status != 0) { hmi = NULL; if (handle != NULL) { dlclose(handle); handle = NULL; } } else { ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle); } *pHmi = hmi; return status;}
HAL层模块文件实际上是.so文件。dlopen以指定模式打开动态库文件,RTLD_NOW 表示立即决定,返回前解除所有未决定的符号,返回一个句柄给进程。dlsym接收句柄
和符号两个参数,返回符号的地址,并使用load函数的第三个参数指向这个符号的地址。其中HAL_MODULE_INFO_SYM_AS_STR的值为“HMI",这样便从HMI的符号确定
hw_module_t结构体的指针。根据HAL模块的编写规范,每个HAL层模块都必须包含一个名为“HMI"的符号,而且这个符号的第一个成员变量的类型必须为hw_module_t。
经过上述的分析可以知道,SensorDevice加载了sensorHAL层的动态库。然后使用sensors_open_l打开设备:
static inline int sensors_open_1(const struct hw_module_t* module, sensors_poll_device_1_t** device) { return module->methods->open(module, SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);}
调用hw_module_t的methods成员的open成员函数打开设备。其中hw_module_t和hw_module_method_t定义如下:
typedef struct hw_module_t { /** tag must be initialized to HARDWARE_MODULE_TAG */ uint32_t tag; /** * The API version of the implemented module. The module owner is * responsible for updating the version when a module interface has * changed. * * The derived modules such as gralloc and audio own and manage this field. * The module user must interpret the version field to decide whether or * not to inter-operate with the supplied module implementation. * For example, SurfaceFlinger is responsible for making sure that * it knows how to manage different versions of the gralloc-module API, * and AudioFlinger must know how to do the same for audio-module API. * * The module API version should include a major and a minor component. * For example, version 1.0 could be represented as 0x0100. This format * implies that versions 0x0100-0x01ff are all API-compatible. * * In the future, libhardware will expose a hw_get_module_version() * (or equivalent) function that will take minimum/maximum supported * versions as arguments and would be able to reject modules with * versions outside of the supplied range. */ uint16_t module_api_version;#define version_major module_api_version /** * version_major/version_minor defines are supplied here for temporary * source code compatibility. They will be removed in the next version. * ALL clients must convert to the new version format. */ /** * The API version of the HAL module interface. This is meant to * version the hw_module_t, hw_module_methods_t, and hw_device_t * structures and definitions. * * The HAL interface owns this field. Module users/implementations * must NOT rely on this value for version information. * * Presently, 0 is the only valid value. */ uint16_t hal_api_version;#define version_minor hal_api_version /** Identifier of module */ const char *id; /** Name of this module */ const char *name; /** Author/owner/implementor of the module */ const char *author; /** Modules methods */ struct hw_module_methods_t* methods; /** module's dso */ void* dso;#ifdef __LP64__ uint64_t reserved[32-7];#else /** padding to 128 bytes, reserved for future use */ uint32_t reserved[32-7];#endif} hw_module_t;
typedef struct hw_module_methods_t { /** Open a specific device */ int (*open)(const struct hw_module_t* module, const char* id, struct hw_device_t** device);} hw_module_methods_t;
由于一个硬件抽象模块可能会包含多个硬件设备,因此在调用hw_module_method_t的open函数时需要指定硬件设备的id。sensors_open_l打开的设备id为
SENSORS_HARDWARE_POLL,在宏定义被定义成“poll",第三个参数device指向打开的设备对应的hw_device_t结构体指针。至此,mSensorModule保存了HAL模块对应
的hw_module_t结构体指针,mSensorDevice保存了hw_device_t指针。
在硬件抽象层模块的实现文件中(Sensors.cpp),有一个名字唯一的struct sensor_module_t变量,名字为HAL_MODULE_INFO_SYM,以Mstar的Sensors.cpp(device目
录下)为例,实现如下。其中hw_module_t成员common的methods为sensors_module_methods指针,这个sensors_module_methods为struct hw_module_methods_t。
HAL_MODULE_INFO_SYM指定了HAL层函数get_sensors_list的本地实现为sensors__get_sensors_list。sensors_module_methods指定了HAL层函数open的本地实现为
open_sensors。
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 = "Nanosic Sensor module", .author = "Nanosic Tec Company", .methods = &sensors_module_methods, .dso = 0, .reserved = {}, }, .get_sensors_list = sensors__get_sensors_list,};
static struct hw_module_methods_t sensors_module_methods = { .open = open_sensors};
static int sensors__get_sensors_list(struct sensors_module_t* module, struct sensor_t const** list){ UNUSE(module);LOGD("call sensors__get_sensors_list, numSensors = %d", numSensors); *list = sSensorList; return numSensors;}
static struct sensor_t sSensorList[LOCAL_SENSORS] = {{ "Accelerometer Sensor", "NGB TVOS", 1, SENSORS_ACCELERATION_HANDLE, SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.3f, 0, 0, 0, 0, 0, 0, 0, {}},{ "Gyroscope Sensor", "NGB TVOS", 1, SENSORS_GYROSCOPE_HANDLE, SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 0, 0, 0, 0, 0, 0, 0, {}},};
来看下open_sensors的实现。首先new了一个struct sensors_poll_context_t的变量。structsensors_poll_context_t有一个struct sensors_poll_device_t的成员device。这里把
device进行初始化,主要是将HAL层的close,activate,setDelay和poll函数的本地实现指定为poll_close,poll_activate,poll_setDelay和poll_poll,使第二个参数指向
sensors_poll_context_t成员device的hw_device_t成员common。这样,sensors_poll_context_t的第一个成员是sensors_poll_device_t。sensors_poll_device_t的第一个成员是
hw_device_t,第二个参数保存的地址是hw_device_t的地址,也就是sensors_poll_device_t和sensors_poll_context_t的首地址。
static int open_sensors(const struct hw_module_t* module, const char* id, struct hw_device_t** device){ UNUSE(id); LOGD("open_sensors()"); int status = -EINVAL; sensors_poll_context_t *dev = new sensors_poll_context_t(); if (!dev->isValid()) { ALOGE("Failed to open the sensors"); return status; } memset(&dev->device, 0, sizeof(sensors_poll_device_t)); dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_0; dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = poll__close; dev->device.activate = poll__activate; dev->device.setDelay = poll__setDelay; dev->device.poll = poll__poll; *device = &dev->device.common; status = 0; return status;}
struct sensors_poll_context_t { struct sensors_poll_device_t device; // must be first sensors_poll_context_t(); ~sensors_poll_context_t(); int activate(int handle, int enabled); int setDelay(int handle, int64_t ns); int pollEvents(sensors_event_t* data, int count); // Will return true if the constructor completed bool isValid() { return mInitialized; };
接着看下sensors_poll_context_t的构造函数。mSensors是一个SensorBase*指针数组,GamepadSensors,VirtualGamepadSensors均继承自SensorBase。这里就是
将sensor放入到mSensors中,初始化三个pollfd,两个监听GamepadSensors和VirtualGamepadSensors的POLLIN事件。此外还创建了管道,监听管道的读端。
SendorBase除了将一些成员变量初始化外,还使用了openInput(mDataName)方法。以GamepadSensor为例,mDataName被初始化为”RealSensor"。openInput以
mDataName作为参数,查找/dev目录下名字带有“hidraw"的设备文件并打开。
enum { gamepad = 0,virtualGamepad, numSensorDrivers, // wake pipe goes here numFds, };
int SensorBase::openInput(const char* inputName) { int fd = -1; mExtConnectedDevice = DeviceMax; if (std::string(REAL_SENSOR_NAME) == std::string(inputName)) { const char *dirname = "/dev"; char devname[PATH_MAX]; char *filename; DIR *dir; struct dirent *de; dir = opendir(dirname); if(dir == NULL) return -1; strcpy(devname, dirname); filename = devname + strlen(devname); *filename++ = '/'; for (int i=0; i < DeviceMax; i++) { HidrawReportDescriptor *pRptDesc = &(sensorDataConfig[i].reportDescriptor); while((de = readdir(dir))) { if((de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))) || (std::string::npos == (std::string(de->d_name).find("hidraw")))) continue; strcpy(filename, de->d_name); LOGD("devname = %s", devname); fd = open(devname, O_RDONLY); if (fd>=0) { int desc_size = 0; struct hidraw_report_descriptor rpt_desc; memset(&rpt_desc, 0x0, sizeof(rpt_desc)); int res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size); if (res < 0) { close(fd); fd = -1; LOGD("!!!Failed: ioctl(fd, HIDIOCGRDESCSIZE, &desc_size)!!!"); } else { rpt_desc.size = desc_size; LOGD("success: ioctl(fd, HIDIOCGRDESCSIZE, &desc_size)"); if (rpt_desc.size <= 0) { close(fd); fd = -1; LOGD("!!!rpt_desc.size <= 0!!!"); break; } res = ioctl(fd, HIDIOCGRDESC, &rpt_desc); if (res < 0) { close(fd); fd = -1; LOGD("!!!Failed: ioctl(fd, HIDIOCGRDESC, &rpt_desc)!!!"); } else { LOGD("rpt_desc.size = %u", rpt_desc.size);#if 0 printf("%s :rpt_desc.size = %u, rpt_desc.value: \n", devname, rpt_desc.size); for (unsigned int j=0; j< rpt_desc.size; j++) { printf("%2x ", rpt_desc.value[j]); } printf("\n");#endif ExtConnectedDevice extConnectedDevice = checkConnectedDeviceByReportDescriptor(rpt_desc); if (extConnectedDevice < DeviceMax) { mExtConnectedDevice = extConnectedDevice; LOGD("______________________FIND REAL SENSOR______________________"); break; } else { close(fd); fd = -1; LOGD("!!!checkConnectedDeviceByReportDescriptor(rpt_desc) return not the Device we wanted!!!"); } } } } else { LOGD("Failed: open(%s, O_RDONLY)", devname); } } if (mExtConnectedDevice < DeviceMax) { break; } } closedir(dir); }ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName);return fd;}
sensors_poll_context_t::sensors_poll_context_t(){ LOGD("in sensors_poll_context_t()"); mInitialized = false; // Must clean this up early or else the destructor will make a mess. memset(mSensors, 0, sizeof(mSensors)); numSensors = LOCAL_SENSORS; mSensors[gamepad] = new GamepadSensors(); mPollFds[gamepad].fd = mSensors[gamepad]->getFd(); mPollFds[gamepad].events = POLLIN; mPollFds[gamepad].revents = 0; mSensors[virtualGamepad] = new VirtualGamepadSensors(); mPollFds[virtualGamepad].fd = mSensors[virtualGamepad]->getFd(); mPollFds[virtualGamepad].events = POLLIN; mPollFds[virtualGamepad].revents = 0; int wakeFds[2]; int result = pipe(wakeFds); ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno)); fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); fcntl(wakeFds[1], F_SETFL, O_NONBLOCK); mWritePipeFd = wakeFds[1]; mPollFds[wake].fd = wakeFds[0]; mPollFds[wake].events = POLLIN; mPollFds[wake].revents = 0; mInitialized = true; LOGD("out sensors_poll_context_t()");}
static int poll__activate(struct sensors_poll_device_t *dev, int handle, int enabled){ FUNC_LOG; sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->activate(handle, enabled);}
get_sensors_list会获取所有可用的sensor设备,每个sensor设备都对应一个sensor_t结构体,函数返回sensor设备的数量。之后,依次激活这些可用的sensor设备。
SensorDevice的主要工作是与HAL层进行通信,打开senser设备,加载HAL层的so文件,获得支持的传感器列表并激活。setCapacity为DefaultKeyedVector分配空间。接着
activate这些设备。前面提到mSensorDevice保存的也就是sensors_poll_device_t的地址,open_sensors将sensors_poll_device_t的activate函数设为poll_activate函数。调用
activate函数也就是调用poll_activate函数,poll_activate转而去调用sensors_poll_context_t的activate函数。
int sensors_poll_context_t::activate(int handle, int enabled){LOGD("sensors_poll_context_t::activate"); if (!mInitialized) return -EINVAL; int index = handleToDriver(handle); if (index < 0) return index; if(mSensors[index]->getState() == -1 && mSensors[index]->getDataName() != NULL) { int fd_t = mSensors[index]->getFd();if(fd_t >= 0) {mSensors[index]->setState(1);} else {mSensors[index]->setState(-1);}} int err = mSensors[index]->enable(handle, enabled); if (!err) { const char wakeMessage(WAKE_MESSAGE); int result = write(mWritePipeFd, &wakeMessage, 1); ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno)); } return err;}
SensorBase::enable函数,这是一个纯虚函数,由子类重写。以GamepadSensor为例,enable实现中调用openDevice打开设备。openDevice打开名为“RealSensor"的
文件,mDevFd保存了文件描述符。回到activate函数,最后往管道里写入一个‘W',以唤醒等待POLLIN事件的休眠线程。
int GamepadSensors::enable(int32_t handle, int enabled){LOGD("GamepadSensors::enable(int32_t handle=%d, int enabled=%d)", handle, enabled);openDevice();return 0;}
int SensorBase::openDevice() {LOGD("openDevice"); if ((mDevFd < 0) && mDevName) { mDevFd = open(mDevName, O_RDONLY); LOGD("mDevFd = open(%s, O_RDONLY), mDevFd=%d", mDevName, mDevFd); ALOGE_IF(mDevFd < 0, "Couldn't open %s (%s)", mDevName, strerror(errno)); } return 0;}
回到onFirstRef函数中,接着对获得的sensor设备列表进行注册:
for (ssize_t i=0 ; i<count ; i++) { registerSensor( new HardwareSensor(list[i]) );
Sensor SensorService::registerSensor(SensorInterface* s){ sensors_event_t event; memset(&event, 0, sizeof(event)); const Sensor sensor(s->getSensor()); // add to the sensor list (returned to clients) mSensorList.add(sensor); // add to our handle->SensorInterface mapping mSensorMap.add(sensor.getHandle(), s); // create an entry in the mLastEventSeen array mLastEventSeen.add(sensor.getHandle(), NULL); return sensor;}
注册虚拟传感器:
if (hasGyro && hasAccel && hasMag) { Sensor aSensor; // Add Android virtual sensors if they're not already // available in the HAL aSensor = registerVirtualSensor( new RotationVectorSensor() );// 虚拟旋转传感器 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) { mUserSensorList.add(aSensor); } aSensor = registerVirtualSensor( new GravitySensor(list, count) );//虚拟重力传感器 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) { mUserSensorList.add(aSensor); } aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );//虚拟加速器 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) { mUserSensorList.add(aSensor); } aSensor = registerVirtualSensor( new OrientationSensor() );//虚拟方向传感器 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) { // if we are doing our own rotation-vector, also add // the orientation sensor and remove the HAL provided one. mUserSensorList.replaceAt(aSensor, orientationIndex); } // virtual debugging sensors are not added to mUserSensorList registerVirtualSensor( new CorrectedGyroSensor(list, count) );//真正陀螺仪 registerVirtualSensor( new GyroDriftSensor() );//虚拟陀螺测漂传感器 }
SensorService继承自Thread,末尾使用run进入SensorService::threadLoop()方法。threadLoop是父类Thread的虚函数,由子类实现。
bool SensorService::threadLoop(){ ALOGD("nuSensorService thread starting..."); // each virtual sensor could generate an event per "real" event, that's why we need // to size numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT. // in practice, this is too aggressive, but guaranteed to be enough. const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT; const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size()); SensorDevice& device(SensorDevice::getInstance()); const size_t vcount = mVirtualSensorList.size(); const int halVersion = device.getHalDeviceVersion(); do { ssize_t count = device.poll(mSensorEventBuffer, numEventMax); if (count < 0) { ALOGE("sensor poll failed (%s)", strerror(-count)); break; } // Reset sensors_event_t.flags to zero for all events in the buffer. for (int i = 0; i < count; i++) { mSensorEventBuffer[i].flags = 0; } // Make a copy of the connection vector as some connections may be removed during the // course of this loop (especially when one-shot sensor events are present in the // sensor_event buffer). Promote all connections to StrongPointers before the lock is // acquired. If the destructor of the sp gets called when the lock is acquired, it may // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for // cleanup. So copy all the strongPointers to a vector before the lock is acquired. SortedVector< sp<SensorEventConnection> > activeConnections; populateActiveConnections(&activeConnections); Mutex::Autolock _l(mLock); // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock, // sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should // not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and // releasing the wakelock. bool bufferHasWakeUpEvent = false; for (int i = 0; i < count; i++) { if (isWakeUpSensorEvent(mSensorEventBuffer[i])) { bufferHasWakeUpEvent = true; break; } } if (bufferHasWakeUpEvent && !mWakeLockAcquired) { setWakeLockAcquiredLocked(true); } recordLastValueLocked(mSensorEventBuffer, count); // handle virtual sensors if (count && vcount) { sensors_event_t const * const event = mSensorEventBuffer; const size_t activeVirtualSensorCount = mActiveVirtualSensors.size(); if (activeVirtualSensorCount) { size_t k = 0; SensorFusion& fusion(SensorFusion::getInstance()); if (fusion.isEnabled()) { for (size_t i=0 ; i<size_t(count) ; i++) { fusion.process(event[i]); } } for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) { for (size_t j=0 ; j<activeVirtualSensorCount ; j++) { if (count + k >= minBufferSize) { ALOGE("buffer too small to hold all events: " "count=%zd, k=%zu, size=%zu", count, k, minBufferSize); break; } sensors_event_t out; SensorInterface* si = mActiveVirtualSensors.valueAt(j); if (si->process(&out, event[i])) { mSensorEventBuffer[count + k] = out; k++; } } } if (k) { // record the last synthesized values recordLastValueLocked(&mSensorEventBuffer[count], k); count += k; // sort the buffer by time-stamps sortEventBuffer(mSensorEventBuffer, count); } } } // handle backward compatibility for RotationVector sensor if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) { for (int i = 0; i < count; i++) { if (mSensorEventBuffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) { // All the 4 components of the quaternion should be available // No heading accuracy. Set it to -1 mSensorEventBuffer[i].data[4] = -1; } } } // Map flush_complete_events in the buffer to SensorEventConnections which called // flush on the hardware sensor. mapFlushEventsToConnections[i] will be the // SensorEventConnection mapped to the corresponding flush_complete_event in // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise). for (int i = 0; i < count; ++i) { mMapFlushEventsToConnections[i] = NULL; if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) { const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor; SensorRecord* rec = mActiveSensors.valueFor(sensor_handle); if (rec != NULL) { mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection(); rec->removeFirstPendingFlushConnection(); } } } // Send our events to clients. Check the state of wake lock for each client and release the // lock if none of the clients need it. bool needsWakeLock = false; size_t numConnections = activeConnections.size(); for (size_t i=0 ; i < numConnections; ++i) { if (activeConnections[i] != 0) { activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch, mMapFlushEventsToConnections); needsWakeLock |= activeConnections[i]->needsWakeLock(); // If the connection has one-shot sensors, it may be cleaned up after first trigger. // Early check for one-shot sensors. if (activeConnections[i]->hasOneShotSensors()) { cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer, count); } } } if (mWakeLockAcquired && !needsWakeLock) { setWakeLockAcquiredLocked(false); } } while (!Thread::exitPending()); ALOGW("Exiting SensorService::threadLoop => aborting..."); abort(); return false;}
ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { if (!mSensorDevice) return NO_INIT; ssize_t c; do { c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), buffer, count); } while (c == -EINTR); return c;}
SensorDevice的poll函数会调用到sensors_poll_device_1的poll函数,前面提到open_sensors将sensors_poll_device_1的poll函数设置为poll_poll函数,poll_poll函
数调用sensors_poll_context_t::pollEvents函数。
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count){ LOGD("---sensors_poll_context_t::pollEvents---"); int nbEvents = 0; int n = 0; do { for (int i=0 ; count && i<numSensorDrivers ; i++) { SensorBase* const sensor(mSensors[i]);bool openFailed = false;bool hungUp = false;if (mSensors[i]->getFd() == -1) {openFailed = true;mSensors[i]->setState(-1);LOGD("failed: open %s!!!", sensorDeviceName[i]);} else {if (mPollFds[i].revents & (POLLHUP | POLLERR)) {hungUp = true;LOGD("%s POLLHUP or POLLERR !!!", sensorDeviceName[i]);}}if (hungUp) {close(mSensors[i]->getFd());}if (openFailed || hungUp) {int fd = -1;if (i == virtualGamepad) {fd = open(static_cast<VirtualGamepadSensors*>(mSensors[virtualGamepad])->getFifoName(), O_RDONLY | O_NONBLOCK);} else {fd = mSensors[i]->openInput(mSensors[i]->getDataName());}if (fd < 0) {mSensors[i]->setState(-1);LOGD("failed reopen %s !!!", sensorDeviceName[i]);} else {mSensors[i]->setState(1);LOGD("success reopen %s !!!", sensorDeviceName[i]);}mSensors[i]->setDataFd(fd);mPollFds[i].fd = mSensors[i]->getFd();mPollFds[i].events = POLLIN;mPollFds[i].revents = 0;}// See if we have some pending events from the last poll() if ((mPollFds[i].revents & (POLLIN | POLLPRI)) || (sensor->hasPendingEvents())) { LOGD("true == ((mPollFds[%d].revents & (POLLIN | POLLPRI)) || (sensor->hasPendingEvents()))", i);int nb = sensor->readEvents(data, count);if (nb < 0) {LOGD("readEvents return = %d",nb);return -errno;} if (nb < count) { // no more data for this sensor mPollFds[i].revents = 0; } count -= nb; nbEvents += nb; data += nb; } } if (count) { do { LOGD("before poll(mPollFds, numFds(%d), nbEvents(%d) ? 0 : -1)", numFds, nbEvents); n = poll(mPollFds, numFds, nbEvents ? 0 : -1); LOGD("mPollFds[0].revents=%d, mPollFds[1].revents=%d", mPollFds[0].revents, mPollFds[1].revents); LOGD("%d = poll(mPollFds, numFds, nbEvents ? 0 : -1)", n); } while (n < 0 && errno == EINTR); if (n < 0) { ALOGE("poll() failed (%s)", strerror(errno)); return -errno; } if (mPollFds[wake].revents & (POLLIN | POLLPRI)) { LOGD("true == (mPollFds[wake].revents & (POLLIN | POLLPRI))"); char msg; int result = read(mPollFds[wake].fd, &msg, 1); ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno)); ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg)); mPollFds[wake].revents = 0; } } LOGD("n=%d, count=%d", n, count); // if we have events and space, go read them } while (n && count); LOGD("---nbEvents=%d---", nbEvents); return nbEvents;}
pollEvent末尾的do-while循环会调用poll使HAL层和kernel进行通信,以监听已被初始化的mPollFds的事件。函数中还遍历了所有的mpollFds,调用readEvents进行处
理。readEvents在SensorBase的子类实现,以GamepadSensor为例,之后就是解析Gyroscope和Accelerometer的数据。
int GamepadSensors::readEvents(sensors_event_t* data, int count){ memset(mRawDataBuf, 0, sizeof(mRawDataBuf)); ssize_t nbytes = read(mDataFd, mRawDataBuf, sizeof(mRawDataBuf)); LOGD("%d = read(mDataFd, mRawDataBuf, sizeof(mRawDataBuf))", nbytes);#if 1 printf("mRawDataBuf: "); for (int i=0; i<nbytes; i++) { printf("%02X ", mRawDataBuf[i]); } printf("\n");#endif int numEventReceived = parseRawData(mRawDataBuf, nbytes, data, count); return numEventReceived;}readEvents函数从打开的InputDevice中读取数据到mRawDataBuf中,末尾调用parseRawData函数读取sensor配置参数。
int GamepadSensors::parseRawData(const char *rawDataBuf, const size_t bufSize, struct sensors_event_t* data, int count){ if ((rawDataBuf == NULL) || (bufSize <= 0) || (data == NULL) || (count < 2)) { return -EINVAL; } ExtConnectedDevice extConnectedDevice= getConnectedDevice(); if (extConnectedDevice >= DeviceMax) { return -EINVAL; } struct timeval t; int eventCount = 0; SensorDataConfig config; memset(&config, 0, sizeof(SensorDataConfig)); int ret = chooseDataConfig(config, extConnectedDevice); if (ret < 0) { return -EINVAL; }//后面部分省略。。。
至此,Android Sensor的HAL层代码已基本分析完。
- Android sensorservice
- android SensorService lightSensor
- Android SensorService学习笔记
- Android SensorService源码分析(一)
- Android SensorService源码分析(二)
- Android SensorService启动流程(一)
- Android SensorService启动流程(二)
- android-5.0 sensor工作原理—sensorservice的启动(一)
- android-5.0 sensor工作原理—sensorservice的启动(二)
- SensorService 分析
- Android sensor架构(二)SystemSensorManager以及JNI、sensorService(and5.1)
- (OK) android-5.0 sensor工作原理—sensorservice的启动(一)
- (OK) android-5.0 sensor工作原理—sensorservice的启动(二)
- Android sensor架构(二)SystemSensorManager以及JNI、sensorService(and5.1)
- Android sensor架构(二)SystemSensorManager以及JNI、sensorService(and5.1)
- SensorService启动分析
- SensorService architechure’ note
- SensorService发生NE分析
- 算法学习笔记--4. 二进制求和
- OpenRecon中build运行出错的解决办法
- 多线程实现图片移动
- NIO编程
- java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to
- Android sensorservice
- js闭包
- ORACLE 数据库 学习第一天
- BZOJ 2223 [Coci 2009]PATULJCI 主席树
- 课时23 YUM软件管理
- [东师培训D3T2] Number
- C Looooops POJ
- Unused import statement
- XML DTD