(OK) android-5.0 sensor工作原理—sensorservice的启动(二)
http://blog.csdn.net/zsj100213/article/details/48287023
3.2 dev.getSensorList(&list);获取厂商在HAL层初始化的sensor_t类型结构体的sSensorList,并返回sensor device的数目。
3.3 registerSensor( new HardwareSensor(list[i]) );在for循环中注册这些sensor。根据硬件sensor_t创建HardwareSensor,然后加入mSensorList(Sensor) 和mSensorMap(HardwareSensor)中,后面的switch是判断是否存在电子罗盘,GYRO以及GYRO对应所需要的对应的一些所对应的一些虚拟sensor
- 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:
- 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;
- }
- 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(), event);
- return sensor;
- }
3.4 mUserSensorList = mSensorList;将mSensorList传感器列表赋值给mUserSensorList,mSensorList是由registerSensor初始化的,mUserSensorList是要提交给Java框架层的传感器列表。
3.5 如果有GYRO就注册这样一些上面提到的三种虚拟sensor来实现GYRO的功能,此处我是这么理解的。
- if (hasGyro) {
- 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() );
- }
3.6 run("SensorService", PRIORITY_URGENT_DISPLAY);启动sensorService线程,sensorService父类有一个Thread线程,调用run方法会创建线程并调用threadLoop方法。
- 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();
- SensorEventAckReceiver sender(this);
- sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
- 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;
- {
- Mutex::Autolock _l(mLock);
- for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != 0) {
- activeConnections.add(connection);
- }
- }
- }
- 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) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
- mWakeLockAcquired = 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) {
- release_wake_lock(WAKE_LOCK_NAME);
- mWakeLockAcquired = false;
- }
- } while (!Thread::exitPending());
- ALOGW("Exiting SensorService::threadLoop => aborting...");
- abort();
- return false;
- }
3.6.1 首先是调用device.poll(mSensorEventBuffer, numEventMax);来获取sensor数据。这里调用的是前面open_sensors函数初始化的 dev->device.poll = poll__poll;
- static int poll__poll(struct sensors_poll_device_t *dev,
- sensors_event_t* data, int count) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->pollEvents(data, count);
- }
可以看到最后调用的是pollEvents函数:
- int sensors_poll_context_t::pollEvents(sensors_event_t * data, int count)
- {
- int nbEvents = 0;
- int n = 0;
- int polltime = -1;
- 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;
- }
- #ifndef ORI_NULL
- if ((0 != nb) && (acc == i)) {
- ((OriSensor *) (mSensors[ori]))->
- setAccel(&data[nb - 1]);
- }
- #endif
- 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
- do {
- n = poll(mPollFds, numFds,
- nbEvents ? 0 : polltime);
- } while (n < 0 && errno == EINTR);
- 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;
- }
这里首先调用的是sensor->readEvents(data, count);也就是各个sensor对应的读取sensor event的方法。readEvents()函数先调用fill函数将所要读的sensor的input_event事件读取到一个环形缓冲区,然后在while循环中mInputReader.readEvent(&event)读取当前指针所指向的事件,mInputReader.next();将指针指向环形队列下一条事件来读取下一条事件。
- int STKLightSensor::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) {
- if (event->code == ABS_MISC) {
- mPendingEvent.light = (float)event->value;
- }
- } else if (type == EV_SYN) {
- mPendingEvent.timestamp = timevalToNano(event->time);
- if (mEnabled) {
- *data++ = mPendingEvent;
- count--;
- numEventReceived++;
- }
- } else {
- ALOGE("STKLightSensor: unknown event (type=%d, code=%d)",
- type, event->code);
- }
- mInputReader.next();
- }
- return numEventReceived;
- }
fill函数的参数data_fd是在前面sensors_poll_context_t()函数中的new STKLightSensor();进行初始化的,其主要是SensorBase(NULL, "lightsensor-level"),这里主要是openInput动作来获得一个fd从而从这个fd的文件中获取sensor
event。
- 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;
- }
- ssize_t InputEventCircularReader::readEvent(input_event const **events)
- {
- *events = mCurr;
- ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
- return available ? 1 : 0;
- }
- void InputEventCircularReader::next()
- {
- mCurr++;
- mFreeSpace++;
- if (mCurr >= mBufferEnd) {
- mCurr = mBuffer;
- }
- }
- 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()实际上是打开各个sensor对应于/dev/input/event*文件节点最后返回的是sensor对应文件节点的fd,也就是上面fill函数的参数data_fd,在adb shell,然后getevent命令也是获取位于/dev/input/下所有的event事件。
- 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;
在获取完数据之后就要通过 activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,mMapFlushEventsToConnections);调用write函数将数据放到一个管道里面,sensor APP将数据取走。
- ssize_t size = SensorEventQueue::write(mChannel,
- reinterpret_cast<ASensorEvent const*>(scratch), count);
至此sensorservice的启动就讲完了,下一篇将从sensor APP端讲述sensor APP的工作流程。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通