Android Sensor HAL层分析
来源:互联网 发布:铁塔基础设计软件 编辑:程序博客网 时间:2024/05/22 03:12
SensorService在SystemServer进程中启动。
/frameworks/base/ervices/java/com/android/server/SystemServer.java
private void startBootstrapServices() { ... startSensorService(); }
startSensorService是一个native函数,其具体实现在com_android_server_SystemServer.cpp的android_server_SystemServer_startSensorService函数中。
/frameworks/base/services/core/jni/com_android_server_SystemServer.cpp
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组件。new SERVICE()参数的传入最终结果是创建SensorService的一个强引用。
/frameworks/native/include/binder/BinderService.h
static void instantiate() { publish(); }
/frameworks/native/include/binder/BinderService.h
static status_t publish(bool allowIsolated = false) { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService( String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); }
onFirstRef函数是RefBase的一个空实现,SensorService继承自RefBase,onFirstRef在第一次被强指针引用时调用,首先是获得一个SensorDevice单例对象。
/frameworks/native/services/sensorservice/SensorService.cpp
void SensorService::onFirstRef() { ALOGD("nuSensorService starting..."); SensorDevice& dev(SensorDevice::getInstance()); ...}
看看SensorDevice的默认构造函数:
/frameworks/native/services/sensorservice/SensorDevice.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_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); } } } }
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结构体地址。
/hardware/libhardware/hardware.c
int hw_get_module(const char *id, const struct hw_module_t **module){ return hw_get_module_by_class(id, NULL, module);}
/hardware/libhardware/hardware.c
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 */ //prop_name为ro.hardware.(name),SensorService传下来的class_id为sensors,则prop_name为ro.hardware.sensors snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name); //获取prop_name的属性值,保存在prop中 if (property_get(prop_name, prop, NULL) > 0) { //输出固定的文件名格式到path中 if (hw_module_exists(path, sizeof(path), name, prop) == 0) {// 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);}
/hardware/libhardware/hardware.c
//紧接上面,32位下生成/vendor/lib/hw.sensors.属性值.so或/system/lib/hw.sensors.属性值.so,64位下生成/vendor/lib64/hw.sensors.属性值.so或/system/lib64/hw.sensors.属性值.sostatic int hw_module_exists(char *path, size_t path_len, const char *name, const char *subname){ snprintf(path, path_len, "%s/%s.%s.so", HAL_LIBRARY_PATH2, name, subname); if (access(path, R_OK) == 0) return 0; snprintf(path, path_len, "%s/%s.%s.so", HAL_LIBRARY_PATH1, name, subname); if (access(path, R_OK) == 0) return 0; return -ENOENT;}
/hardware/libhardware/hardware.c
//尝试去加载上面路径的so文件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 */ //dlopen以暂缓决定模式打开指定的动态连接库文件,并返回一个句柄给调用进程 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. */ //dlsym通过句柄和连接符名称获取函数名或者变量名,返回符号的地址 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_MODULE_INFO_SYM_AS_STR的符号,HAL_MODULE_INFO_SYM_AS_STR在宏定义中被定义为“HMI”,在这里HAL_MODULE_INFO_SYM_AS_STR是struct sensors_module_t的变量,struct sensors_module_t第一个成员common为struct hw_module_t类型。因为common成员和HAL_MODULE_INFO_SYM_AS_STR首地址相同,所以load函数末尾可以安全地将第二个参数的地址指向这个符号的地址。所以SensorDevice中类型为struct sensors_module_t*的mSensorModule成员指向了HAL_MODULE_INFO_SYM_AS_STR符号的地址。
/hardware/libhardware/include/hardware/sensors.h
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);};
此时,sensor模块的so已加载完成。回到SensorDevice的构造函数中,接着调用sensors_open_1函数打开sensor设备。sensors_open_1没有在SensorDevice.cpp中实现,而是在HAL层实现。
/frameworks/native/services/sensorservice/SensorDevice.cpp
...if (mSensorModule) { err = sensors_open_1(&mSensorModule->common, &mSensorDevice); ...
/hardware/libhardware/include/hardware/sensors.h
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);}
该函数接收sensors_module_t的common成员的指针(struct hw_module_t*类型)作为第一个参数,调用参数的struct hw_module_methods_t*类型的methods成员的唯一函数指针成员,即open函数。其中,SENSORS_HARDWARE_POLL在宏定义被定义为“poll”。
/hardware/libhardware/include/hardware/hardware.h
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;
/hardware/libhardware/include/hardware/hardware.h
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;
sensors.h为我们提供了HAL层的接口,实现部分则在sensors.c或sensors.cpp完成。sensors.cpp定义了一个hw_module_methods_t类型的变量sensors_module_methods,并且指定open函数的实现为open_sensors函数。
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
static struct hw_module_methods_t sensors_module_methods = { .open = open_sensors};
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
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;}
open_sensors函数首先new了一个sensors_poll_context_t对象。
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
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 setDelay_sub(int handle, int64_t ns); int pollEvents(sensors_event_t* data, int count);private: enum { acc = 0, akm = 1, numSensorDrivers, numFds, }; static const size_t wake = numFds - 1; static const char WAKE_MESSAGE = 'W'; struct pollfd mPollFds[numFds]; int mWritePipeFd; SensorBase* mSensors[numSensorDrivers]; /* These function will be different depends on * which sensor is implemented in AKMD program. */ int handleToDriver(int handle); int proxy_enable(int handle, int enabled); int proxy_setDelay(int handle, int64_t ns);};
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
sensors_poll_context_t::sensors_poll_context_t(){#ifdef SENSORHAL_ACC_ADXL346 mSensors[acc] = new AdxlSensor();#endif#ifdef SENSORHAL_ACC_KXTF9 mSensors[acc] = new KionixSensor();#endif mPollFds[acc].fd = mSensors[acc]->getFd(); mPollFds[acc].events = POLLIN; mPollFds[acc].revents = 0; mSensors[akm] = new AkmSensor(); mPollFds[akm].fd = mSensors[akm]->getFd(); mPollFds[akm].events = POLLIN; mPollFds[akm].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;}
sensors_poll_context_t的构造函数主要工作是使用poll监听AdxlSensor,KionixSensor和创建的管道读端的POLLIN事件。
回到open_sensors函数,接着对sensors_poll_context_t的成员作初始化。sensors_poll_context_t的首个成员为sensors_poll_device_t,而sensors_poll_device_t的首个成员是hw_device_t,这三个类型的变量首地址是相同的,所以它们的指针可以相互安全地进行转换。最后把传下来的第二个指针参数指向已被初始化的hw_device_t成员地址。
hw_get_module和sensors_open_1这两个函数保存了HAL层对应的hw_module_t类型和hw_device_t类型的指针。再次返回SenosrDevice的构造函数,接下来用get_sensors_list去获取sensor的列表。
/frameworks/native/services/sensorservice/SensorDevice.cpp
...sensor_t const* list;ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);mActivationCount.setCapacity(count);...
同样地,get_sensors_list方法的设置出现在HMI符号中,然后调到sensors__get_sensors_list方法,最后获取到struct sensor_t数组,并使传下来的第二个参数指向该数组的地址,其中sensor_t的作用是记录sensor的信息参数,一个sensor设备对应一个sensor_t结构体。
/hardware/akm/AK8975_FS/libsensors/Sensors.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 = "AKM Sensor module", .author = "Asahi Kasei Microdevices", .methods = &sensors_module_methods, .dso = NULL, .reserved = {0}, }, .get_sensors_list = sensors__get_sensors_list,};
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
static int sensors__get_sensors_list(struct sensors_module_t* module, struct sensor_t const** list){ *list = sSensorList; return ARRAY_SIZE(sSensorList);}
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
static const struct sensor_t sSensorList[] = { { "AK8975 3-axis Magnetic field sensor", "Asahi Kasei Microdevices", 1, SENSORS_MAGNETIC_FIELD_HANDLE, SENSOR_TYPE_MAGNETIC_FIELD, 1228.8f, CONVERT_M, 0.35f, 10000, 0, 0, 0, 0, 0, 0, { } },#ifdef SENSORHAL_ACC_ADXL346 { "Analog Devices ADXL345/6 3-axis Accelerometer", "ADI", 1, SENSORS_ACCELERATION_HANDLE, SENSOR_TYPE_ACCELEROMETER, (GRAVITY_EARTH * 16.0f), (GRAVITY_EARTH * 16.0f) / 4096.0f, 0.145f, 10000, 0, 0, 0, 0, 0, 0, { } }, { "AK8975 Orientation sensor", "Asahi Kasei Microdevices", 1, SENSORS_ORIENTATION_HANDLE, SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 0.495f, 10000, 0, 0, 0, 0, 0, 0, { } }#endif#ifdef SENSORHAL_ACC_KXTF9 { "Kionix KXTF9 3-axis Accelerometer", "Kionix", 1, SENSORS_ACCELERATION_HANDLE, SENSOR_TYPE_ACCELEROMETER, (GRAVITY_EARTH * 2.0f), (GRAVITY_EARTH) / 1024.0f, 0.7f, 10000, 0, 0, 0, 0, 0, 0, { } }, { "AK8975 Orientation sensor", "Asahi Kasei Microdevices", 1, SENSORS_ORIENTATION_HANDLE, SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 1.05f, 10000, 0, 0, 0, 0, 0, 0, { } }#endif};
回到SensorDevice的构造函数中,最后一步是使用activate方法对上面sensor列表的sensor进行激活。同理,activate方法最终会调到sensors_poll_context_t::activate方法。
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
static int poll__activate(struct sensors_poll_device_t *dev, int handle, int enabled) { sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->activate(handle, enabled);}
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
int sensors_poll_context_t::activate(int handle, int enabled) { int drv = handleToDriver(handle); int err; switch (handle) { case ID_A: case ID_M: /* No dependencies */ break; case ID_O: /* These sensors depend on ID_A and ID_M */ mSensors[handleToDriver(ID_A)]->setEnable(ID_A, enabled); mSensors[handleToDriver(ID_M)]->setEnable(ID_M, enabled); break; default: return -EINVAL; } err = mSensors[drv]->setEnable(handle, enabled); if (enabled && !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;}
下面以AdxlSensor为例进行说明:
如果AdxlSensor没有被激活且enabled参数为1,只将mEnables加1。
如果AdxlSensor已经被首次激活了,则往/sys/class/input/(input_name)/device/device/disable中写入“1”,将mEnable减1。注意到这里传下来的enabled参数为0,AdxlSensor构造函数中把mEnabled初始化为0,也就是说SensorDevice初始化时不会将相关Sensor使能,要使Sensor使能,需要应用层调到native层使能。
/hardware/akm/AK8975_FS/libsensors/AdxlSensor.cpp
int AdxlSensor::setEnable(int32_t handle, int enabled) { int err = 0; char buffer[2]; /* handle check */ if (handle != ID_A) { ALOGE("AdxlSensor: Invalid handle (%d)", handle); return -EINVAL; } buffer[0] = '\0'; buffer[1] = '\0'; if (mEnabled <= 0) { if(enabled) buffer[0] = '0'; } else if (mEnabled == 1) { if(!enabled) buffer[0] = '1'; } if (buffer[0] != '\0') { strcpy(&input_sysfs_path[input_sysfs_path_len], "disable"); err = write_sys_attribute(input_sysfs_path, buffer, 1); if (err != 0) { return err; } ALOGD("AdxlSensor: Control set %s", buffer); setInitialState(); } if (enabled) { mEnabled++; if (mEnabled > 32767) mEnabled = 32767; } else { mEnabled--; if (mEnabled < 0) mEnabled = 0; } ALOGD("AdxlSensor: mEnabled = %d", mEnabled); return err;}
AdxlSensor传给SensorBase构造函数的两个参数分别是NULL, ADXL_DATA_NAME,在宏定义被定义为”ADXL34x accelerometer”。之后调用openInput(ADXL_DATA_NAME)打开输入设备。
/hardware/akm/AK8975_FS/libsensors/SensorBase.cpp
SensorBase::SensorBase( const char* dev_name, const char* data_name) : dev_name(dev_name), data_name(data_name), dev_fd(-1), data_fd(-1){ if (data_name) { data_fd = openInput(data_name); }}
openInput函数在/dev/input目录下查找设备名称。Linux内核提供了一个Input子系统,Input子系统会在/dev/input/路径下创建我们硬件输入设备的节点,一般情况下在我们的手机中这些节点是以eventXX来命名的,如event0,event1等等,可以利用EVIOCGNAME获取此事件结点名称。open(devname, O_RDONLY)打开了设备节点,strcpy(input_name, filename)将设备名拷贝到input_name中。
/hardware/akm/AK8975_FS/libsensors/SensorBase.cpp
int SensorBase::openInput(const char* inputName) { int fd = -1; const char *dirname = "/dev/input"; 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++ = '/'; while((de = readdir(dir))) { if(de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))) continue; strcpy(filename, de->d_name); fd = open(devname, O_RDONLY); if (fd>=0) { char name[80]; if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { name[0] = '\0'; } if (!strcmp(name, inputName)) { strcpy(input_name, filename); break; } else { close(fd); fd = -1; } } } closedir(dir); ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName); return fd;}
这样,SensorDevice的构造函数便介绍完毕。
回到SensorService的onFirstRef函数,SensorService继承自Thread,函数末尾调用run进入threadLoop方法。
/frameworks/native/services/sensorservice/SensorService.cpp
...run("SensorService", PRIORITY_URGENT_DISPLAY);...
threadLoop方法中调用了SensorDevice::poll方法,mSensorEventBuffer是一个struct sensors_event_t数组。每个传感器的数据都由struct sensors_event_t表示。
/frameworks/native/services/sensorservice/SensorService.cpp
...do { ssize_t count = device.poll(mSensorEventBuffer, numEventMax); if (count < 0) { ALOGE("sensor poll failed (%s)", strerror(-count)); break; }...
/hardware/libhardware/include/hardware/sensors.h
typedef struct sensors_event_t { /* must be sizeof(struct sensors_event_t) */ int32_t version; /* sensor identifier */ int32_t sensor; /* sensor type */ int32_t type; /* reserved */ int32_t reserved0; /* time is in nanosecond */ int64_t timestamp; union { union { float data[16]; /* acceleration values are in meter per second per second (m/s^2) */ sensors_vec_t acceleration; /* magnetic vector values are in micro-Tesla (uT) */ sensors_vec_t magnetic; /* orientation values are in degrees */ sensors_vec_t orientation; /* gyroscope values are in rad/s */ sensors_vec_t gyro; /* temperature is in degrees centigrade (Celsius) */ float temperature; /* distance in centimeters */ float distance; /* light in SI lux units */ float light; /* pressure in hectopascal (hPa) */ float pressure; /* relative humidity in percent */ float relative_humidity; /* uncalibrated gyroscope values are in rad/s */ uncalibrated_event_t uncalibrated_gyro; /* uncalibrated magnetometer values are in micro-Teslas */ uncalibrated_event_t uncalibrated_magnetic; /* heart rate data containing value in bpm and status */ heart_rate_event_t heart_rate; /* this is a special event. see SENSOR_TYPE_META_DATA above. * sensors_meta_data_event_t events are all reported with a type of * SENSOR_TYPE_META_DATA. The handle is ignored and must be zero. */ meta_data_event_t meta_data; }; union { uint64_t data[8]; /* step-counter */ uint64_t step_counter; } u64; }; /* Reserved flags for internal use. Set to zero. */ uint32_t flags; uint32_t reserved1[3];} sensors_event_t;
SensorDevice::poll函数最终会调到sensors_poll_context_t::pollEvents函数。
/frameworks/native/services/sensorservice/SensorDevice.cpp
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;}
如果前面监听的Sensor描述符(AdxlSensor和KionixSensor)发生了POLLIN事件或者有未处理的事件,则调用readEvents去处理这些事件。readEvents返回值nb为读得的事件数量,count为传回上层的事件容量,data记录了sensors_event_t结构体数组的当前保存位置。每次读出事件后,都会对这三个变量作处理。
如果还有剩余容量(count>0),则会抓住最后机会使用poll争取获得事件,nbEvents记录了每次进入pollEvents读到的事件总数量。若nbEvents大于0,poll的时间参数为0,表示立即返回;若nbEvents等于0,poll的时间参数为-1,表示一直阻塞到读取到事件。若此时有线程从管道唤醒poll,则会对唤醒事件作处理(实质就是使 mPollFds[wake]的revents恢复默认值)。若poll成功读取到事件且还有剩余容量,则再次进入pollEvents的主循环。
第一次进入pollEvents函数时,由于还没有poll,mPollFds中的所有Sensor的fd都不会有变化,所以会阻塞在poll调用中,直到Sensor发生了事件或者有线程从管道将其唤醒。之后再次进入主循环调用readEvents读取Sensor事件(如果Sensor发生POLLIN事件的话),count没有满的情况下,然后再次进入poll函数,这样一直循环下去,直到poll没有事件返回且没有事件容量才会退出循环。
/hardware/akm/AK8975_FS/libsensors/Sensors.cpp
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count){ int nbEvents = 0; int n = 0; do { // see if we have some leftover from the last poll() for (int i=0 ; count && i<numSensorDrivers ; i++) { SensorBase* const sensor(mSensors[i]); if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) { int nb = sensor->readEvents(data, count); if (nb < count) { // no more data for this sensor mPollFds[i].revents = 0; } if ((0 != nb) && (acc == i)) { ((AkmSensor*)(mSensors[akm]))->setAccel(&data[nb-1]); } count -= nb; nbEvents += nb; data += nb; } } if (count) { // we still have some room, so try to see if we can get // some events immediately or just wait if we don't have // anything to return n = poll(mPollFds, numFds, nbEvents ? 0 : -1); if (n<0) { ALOGE("poll() failed (%s)", strerror(errno)); return -errno; } if (mPollFds[wake].revents & POLLIN) { 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; } } // if we have events and space, go read them } while (n && count); return nbEvents;}
readEvents中如果有未处理事件,则将sensors_event_t类型的未处理事件指针保存在第一个参数中。mInputReader类型为class InputEventCircularReader,是用来填充struct input_event输入事件的环形缓冲区。data_fd为openInput的返回值,即打开的输入设备的fd。AdxlSensor的构造函数将4传给InputEventCircularReader构造函数参数,mBuffer初始化为8个input_event大小的内存,以暂存读取超出环形缓冲区的部分。mBufferEnd指向环形缓冲的末尾,mHead记录了下次填充input_event的位置,mCurr记录了最后一个填充的input_event的位置,mFreeSpace记录了空闲的input_event大小的内存块数量。fill函数从输入设备中读取input_event事件到环形缓冲区中,当读取的大小超过缓冲区大小时,会将超出部分覆盖到缓冲区起始部分。
while循环里读取mCurr记录的input_event的类型来执行操作,循环的条件是环形缓冲区还有数据可以读且需要读取事件的余量count大于0。AdxlSensor是一个加速度传感器,读取的事件类型为EV_ABS,可以用来判断手机屏幕的方向。x轴,y轴是以屏幕左下角为原点向右和向上的方向,z轴是垂直于屏幕指向屏幕外面的方向。在一个时刻,只有一个轴读取到加速度值。使用ADXL_UNIT_CONVERSION宏将内核层读到的重力加速度值转化为标准单位重力加速度值。在三轴上计算得到的数据用以初始化一个mPendingEvent。读取事件类型为EV_SYN时(EV_SYN是用于事件间的分割标志。事件可能按时间或空间进行分割,就像在多点触摸协议中的例子),设定mPendingEvent的时间戳为输入事件发生的时间,将mPendingEvent指针保存在data参数中。这样,readEvents函数将底层传上来的input_event填充到入参data中。SensorService便保存了来自底层的input_event包装而成的sensors_event_t事件。readEvents的返回值就是保存到data参数中的
input_event数量。
值得注意的是,readEvents的入参data是对sensors_poll_context_t::pollEvents的入参data指针值的拷贝,readEvents中能改变data指向的数组的内容,但不能改变指针的指向的位置。所以,当readEvents函数返回了读取的事件数时,sensors_poll_context_t::pollEvents的入参data表示的数组内容已经改变,指向的位置和调用readEvents前的位置相同。
/hardware/akm/AK8975_FS/libsensors/AdxlSensor.cpp
int AdxlSensor::readEvents(sensors_event_t* data, int count){ if (count < 1) return -EINVAL; if (mHasPendingEvent) { mHasPendingEvent = false; mPendingEvent.timestamp = getTimestamp(); *data = mPendingEvent; return mEnabled ? 1 : 0; } ssize_t n = mInputReader.fill(data_fd); if (n < 0) return n; int numEventReceived = 0; input_event const* event; while (count && mInputReader.readEvent(&event)) { int type = event->type; if (type == EV_ABS) { float value = event->value; if (event->code == EVENT_TYPE_ACCEL_X) { mPendingEvent.acceleration.x = ADXL_UNIT_CONVERSION(value); } else if (event->code == EVENT_TYPE_ACCEL_Y) { mPendingEvent.acceleration.y = ADXL_UNIT_CONVERSION(value); } else if (event->code == EVENT_TYPE_ACCEL_Z) { mPendingEvent.acceleration.z = ADXL_UNIT_CONVERSION(value); } } else if (type == EV_SYN) { mPendingEvent.timestamp = timevalToNano(event->time); if (mEnabled) { *data++ = mPendingEvent; count--; numEventReceived++; } } else { ALOGE("AdxlSensor: unknown event (type=%d, code=%d)", type, event->code); } mInputReader.next(); } return numEventReceived;}
/hardware/akm/AK8975_FS/libsensors/InputEventReader.h
class InputEventCircularReader{ struct input_event* const mBuffer; struct input_event* const mBufferEnd; struct input_event* mHead; struct input_event* mCurr; ssize_t mFreeSpace;public: InputEventCircularReader(size_t numEvents); ~InputEventCircularReader(); ssize_t fill(int fd); ssize_t readEvent(input_event const** events); void next();};
/hardware/akm/AK8975_FS/libsensors/InputEventReader.h
InputEventCircularReader::InputEventCircularReader(size_t numEvents) : mBuffer(new input_event[numEvents * 2]), mBufferEnd(mBuffer + numEvents), mHead(mBuffer), mCurr(mBuffer), mFreeSpace(numEvents){}
/hardware/akm/AK8975_FS/libsensors/InputEventReader.cpp
ssize_t InputEventCircularReader::fill(int fd){ size_t numEventsRead = 0; if (mFreeSpace) { const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event)); if (nread<0 || nread % sizeof(input_event)) { // we got a partial event!! return nread<0 ? -errno : -EINVAL; } numEventsRead = nread / sizeof(input_event); if (numEventsRead) { mHead += numEventsRead; mFreeSpace -= numEventsRead; if (mHead > mBufferEnd) { size_t s = mHead - mBufferEnd; memcpy(mBuffer, mBufferEnd, s * sizeof(input_event)); mHead = mBuffer + s; } } } return numEventsRead;}
/bionic/libc/kernel/uapi/linux
struct input_event { //按键时间 struct timeval time; //类型 __u16 type; //模拟成的按键 __u16 code; //按下还是释放 __s32 value;};
至此,Android Sensor的HAL层代码大致分析完毕。
- Android Sensor HAL层分析
- Android Sensor详解(8)sensor hal层分析第一篇
- Sensor系列二 HAL层分析
- Android HAL层分析
- Sensor -- HAL 分析
- Andriod Sensor HAL 分析
- sensor----HAL分析
- Android Hal层简要分析
- Android Hal层简要分析
- Android 传感器hal层分析
- Android Hal层简要分析
- Android Hal层简要分析
- Android HAL层简要分析
- Android Hal层简要分析
- Android Hal层简要分析
- Android从Hal到framework层添加自定义Sensor
- Android sensor hal 详解
- Sensor HAL框架分析之一
- 我们在提供api或微服务时,通常借助openresty nginx进行流量转发或者添加一些规则或功能,
- Django 学习笔记(七)数据库基本操作(增查改删)
- android长图框架
- Android MediaPlayer框架分析
- 以太坊挖矿软件反抽水-eth 免抽水破解收费小插件 (完美兼容 Claymore 原版内核,长沙矿工,圣骑士,中国矿工,ETH 超级矿工)
- Android Sensor HAL层分析
- FTPrep, 49 Anagram
- mysql开启允许远程连接
- 线程实现方法
- Java线程池原理及几种线程池类型介绍
- 关于react-native的适配与布局方式
- 【Leetcode】【python】Merge k Sorted Lists
- YP2.1 Bits and Data Types (双语)
- Android并发编程之全方位解析AsyncTask