以原相心率传感器为例进行分析:
原相心率传感器驱动pixart_hc_driver.c,主要通过采集寄存器数据放入_ppg_mems_data结构体然后通过input输入子系统将事件上报。
input_report_abs(ofndata.pah8001_input_dev, ABS_X, *(uint32_t *) (_ppg_mems_data [_write_index].HRD_Data)) input_report_abs(ofndata.pah8001_input_dev, ABS_Y, *(uint32_t *) (_ppg_mems_data [_write_index].HRD_Data + 4)) input_report_abs(ofndata.pah8001_input_dev, ABS_Z, *(uint32_t *) (_ppg_mems_data [_write_index].HRD_Data + 8)) input_sync(ofndata.pah8001_input_dev)
最后所有上报的事件都会被写入传感器的设备文件,通过监听设备文件即可得到上报的事件。
具体的hal层实现由厂商自己实现,而原相心率传感器hal层代码在HerateSensorPixart.cpp中实现。该层主要功能是读取设备文件中的事件,即_ppg_mems_data结构体中的13个数据,心率数据的合成由这13个数据以及gsensor的三个数据组成。因此还打开了gsensor传感器并获取3个gsensor的数据。并实现一系列的方法供上层调用;
首先定义了一个传感器类型
static sensor_t sSensor = { "Heart rate sensor", "PixArt", 1, SENSORS_PIXART_HEART_RATE_HANDLE, SENSOR_TYPE_HEART_RATE, 1100.0f, 0.005f, 0.005f, 10000, { }};
然后定义了一些全局变量并打开设备文件返回fd:
HeartRateSensorPixArt::HeartRateSensorPixArt() : SensorBase(PIXART_DEVICE_PATH, NULL), mExit(false), gsensor_fd(-1), mExist(false), mEnabled(false), mDelay(-1), mMainReadFd(-1), mMainWriteFd(-1), mWorkerReadFd(-1), mWorkerWriteFd(-1), mStartThread(false), mHeartRate(-1), mHeartRateStatus(0), mStatusChanged(false), mTouchStatus(false), mGradeChanged(false), mSensorName("PixArt Heart Rate"), mAlgHeartRatePixArt(NULL), mSensorListener(NULL){ open_device(); if (dev_fd >= 0) { mExist = initialize(); } if (!mExist) LOGI("NO PixArt Heart Rate sensor!"); else LOGI("PixArt Heart Rate sensor initialize done.");}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
并初始化了一个管道进行数据的传输;最后得到合成的心率数据并向管道中传输数据;
if (heartRate >= 0) hs->mHeartRate = heartRate; if (hs->mStatusChanged || heartRateChange) { char msg = 'h'; retval = write(hs->mWorkerWriteFd, &msg, 1);
这里还有一个函数connectToSensorService(),这里是实现了传感器在SensorEventListener上的注册,只有注册了这个接口才会启动线程。
void HeartRateSensorPixArt::connectToSensorService(){ int retval = 0; mSensorListener = new SensorListener(); if ((mSensorListener != NULL) && mSensorListener.get()) { retval = mSensorListener->initialize(); if (retval != NO_ERROR) { mSensorListener.clear(); mSensorListener = NULL; } }}
接下来由上层的Sensor_mpl.cpp new出一个
HeartRateSensorPixArt的对象获取里面的方法。 if (!strcmp(gId, SENSORS_HARDWARE_POLL_FOR_IWDS)) { mHeartRateSensorPixArt = new HeartRateSensorPixArt(); if (!mHeartRateSensorPixArt->isExist()) { delete mHeartRateSensorPixArt; mHeartRateSensorPixArt = NULL; } else { sensorsForIwds += mHeartRateSensorPixArt->populateSensorList(&sSensorListForIwds[sensorsForIwds]); } } else { mHeartRateSensorPixArt = NULL; }
通过mHeartRateSensorPixArt->getFd()方法得到管道的另一端读数据的fd,最后打开管道读取数据
else if (fd == pixart_heart_rate) { if (mHeartRateSensorPixArt != NULL) { mPollFds[i].revents = 0; char buf[8]; int ret = read(mPollFds[i].fd, buf, sizeof(buf)); if (ret == -1) { ALOGE("poll pixart heart pipe fd error!%d %c", ret, buf[0]); } else { nb = mHeartRateSensorPixArt->readEvents(data, count); if (nb > 0) { count -= nb; nbEvents += nb; data += nb; } } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
open_sensor中包装了一系列操作方法,其中大部分都是调用到了HerateSensorPixart.cpp中的实现方法。
static int open_sensors(const struct hw_module_t* module, const char* id, struct hw_device_t** device){ FUNC_LOG; int status = -EINVAL; gId = strdup(id); sensors_poll_context_t *dev = new sensors_poll_context_t(); memset(&dev->device, 0, sizeof(sensors_poll_device_t)); dev->device.common.tag = HARDWARE_DEVICE_TAG; dev->device.common.version = 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; dev->device.calibrate = poll__calibrate; dev->device.setRightHand = poll__setRightHand; *device = &dev->device.common; status = 0; return status;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
在接下来是JNI层的实现了,代码在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(&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); } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
通过hw_get_module这个接口来获取HAL层调用,关键是SENSORS_HARDWARE_MODULE_ID这个唯一标识;最后获得mSensorDevice这个结构体,里面包含了HAL层中的所有函数实现;包括对传感器是能。
接下来是就是Framwork层的分析了
这里我们把它分为客户端和服务端,服务端主要是从HAL读取数据并将数据写入到管道中,客户端主要是从管道中读出数据。
客户端主要类
SensorManager.Java
从android4.1开始,把SensorManager定义为一个抽象类,定义了一些主要的方法,类主要是应用层直接使用的类,提供给应用层的接口
SystemSensorManager.java
继承于SensorManager,客户端消息处理的实体,应用程序通过获取其实例,并注册监听接口,获取sensor数据
sensorEventListener接口
用于注册监听的接口
sensorThread
是SystemSensorManager的一个内部类,开启一个新线程负责读取读取sensor数据,当注册了sensorEventListener接口的时候才会启动线程
android_hardware_SensorManager.cpp
负责与java层通信的JNI接口
SensorManager.cpp
sensor在Native层的客户端,负责与服务端SensorService.cpp的通信
SenorEventQueue.cpp
消息队列
服务端主要类
SensorService.cpp
服务端数据处理中心
SensorEventConnection
从BnSensorEventConnection继承来,实现接口ISensorEventConnection的一些方法,ISensorEventConnection在SensorEventQueue会保存一个指针,指向调用服务接口创建的SensorEventConnection对象
Bittube.cpp
在这个类中创建了管道,用于服务端与客户端读写数据
SensorDevice
负责与HAL读取数据
客户端主要实现:
APK监听
获取sensor service对象
mService = (SensorServiceManager) serviceClient.getServiceManagerContext(); private void registerSensors() { mHeartRateSensor = mService.getDefaultSensor(Sensor.TYPE_HEART_RATE); if (mHeartRateSensor != null) { mService.registerListener(mListener, mHeartRateSensor, 0); } }
监听数据变化获取心率数据
private SensorEventListener mListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { if (event.sensorType == Sensor.TYPE_HEART_RATE) { Log.d(SUB_TAG, "Update Heart Rate : " + event.values[0]); mHeartRateData = event.values[0]; } mHeartRateText.setText("Heart Rate: " + mHeartRateData); }初始化SystemSensorManager public SystemSensorManager(Context context,Looper mainLooper) { mMainLooper = mainLooper; mContext = context; synchronized(sListeners) { if (!sSensorModuleInitialized) { sSensorModuleInitialized = true; nativeClassInit(); sensors_module_init(); final ArrayList<Sensor> fullList = sFullSensorsList; int i = 0; do { Sensor sensor = new Sensor(); i = sensors_module_get_next_sensor(sensor, i); if (i>=0) { fullList.add(sensor); sHandleToSensor.append(sensor.getHandle(), sensor); } } while (i>0); sPool = new SensorEventPool( sFullSensorsList.size()*2 ); sSensorThread = new SensorThread(); } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
系统开机启动的时候,会创建SystemSensorManager的实例,在其构造函数中,主要做了四件事情:
初始化JNI
调用JNI函数nativeClassInit()进行初始化
初始化Sensor列表
调用JNI函数sensors_module_init,对Sensor模块进行初始化。创建了native层SensorManager的实例。
获取Sensor列表
调用JNI函数sensors_module_get_next_sensor()获取Sensor,并存在sHandleToSensor列表中
构造SensorThread类
构造线程的类函数,并没有启动线程,当有应用注册的时候才会启动线程
启动SensorThread线程读取消息队列中数据
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, int delay, Handler handler) { synchronized (sListeners) { ListenerDelegate l = null; for (ListenerDelegate i : sListeners) { if (i.getListener() == listener) { l = i; } } ……. if (l == null) { l = new ListenerDelegate(listener, sensor, handler); sListeners.add(l); …… if (sSensorThread.startLocked()) { if (!enableSensorLocked(sensor, delay)) { ……. } …… } else if (!l.hasSensor(sensor)) { l.addSensor(sensor); if (!enableSensorLocked(sensor, delay)) { …… } } } return result; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
当有应用程序调用registerListenerImpl()方法注册监听的时候,会调用SensorThread.startLoacked()启动线程,线程只会启动一次,并调用enableSensorLocked()接口对指定的sensor使能,并设置采样时间。
SensorThreadRunnable实现了Runnable接口,在SensorThread类中被启动 boolean startLocked() { try { if (mThread == null) { SensorThreadRunnable runnable = new SensorThreadRunnable(); Thread thread = new Thread(runnable, SensorThread.class.getName()); thread.start(); synchronized (runnable) { while (mSensorsReady == false) { runnable.wait(); } } }private class SensorThreadRunnable implements Runnable { SensorThreadRunnable() { } private boolean open() { sQueue = sensors_create_queue(); return true; } public void run() { ……. if (!open()) { return; } synchronized (this) { mSensorsReady = true; this.notify(); } while (true) { final int sensor = sensors_data_poll(sQueue, values, status, timestamp); ……. } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
在open函数中调用JNI函数sensors_create_queue()来创建消息队列,然后调用SensorManager. createEventQueue()创建。
在startLocked函数中启动新的线程后,做了一个while的等待while (mSensorsReady == false),只有当mSensorsReady等于true的时候,才会执行enableSensorLocked()函数对sensor使能。而mSensorsReady变量,是在open()调用创建消息队列成功之后才会true,所以我们认为,三个功能调用顺序是如下:
调用open函数创建消息队列
调用enableSensorLocked()函数对sensor使能
调用sensors_data_poll从消息队列中读取数据,而且是在while (true)循环里一直读取
我们首先来分析服务端的实现
启动SensorService服务
在SystemServer进程中的main函数中,通过JNI调用,调用到
com_android_server_SystemServer.cpp的android_server_SystemServer_init1()方法,该方法又调用system_init.cpp中的system_init():
extern "C" status_t system_init(){ …… property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { SensorService::instantiate(); } ….. return NO_ERROR;}
在这里创建了SensorService的实例。
SensorService初始化
SensorService创建完之后,将会调用SensorService::onFirstRef()方法,在该方法中完成初始化工作。
首先获取SensorDevice实例,在其构造函数中,完成了对Sensor模块HAL的初始化:
SensorDevice::SensorDevice() : mSensorDevice(0), mSensorModule(0){ status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule); 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); } } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
这里主要做了三个工作:
调用HAL层的hw_get_modele()方法,加载Sensor模块so文件
调用sensor.h的sensors_open方法打开设备
调用sensors_poll_device_t->activate()对Sensor模块使能
再来看看SensorService::onFirstRef()方法:
void SensorService::onFirstRef(){ SensorDevice& dev(SensorDevice::getInstance()); if (dev.initCheck() == NO_ERROR) { sensor_t const* list; ssize_t count = dev.getSensorList(&list); if (count > 0) { …… for (ssize_t i=0 ; i<count ; i++) { registerSensor( new HardwareSensor(list[i]) ); …… } const SensorFusion& fusion(SensorFusion::getInstance()); if (hasGyro) { …… } …… run("SensorService", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
在这个方法中,主要做了4件事情:
创建SensorDevice实例
获取Sensor列表
调用SensorDevice.getSensorList(),获取Sensor模块所有传感器列表
为每个传感器注册监听器
registerSensor( new HardwareSensor(list[i]) );void SensorService::registerSensor(SensorInterface* s){ sensors_event_t event; memset(&event, 0, sizeof(event)); const Sensor sensor(s->getSensor()); mSensorList.add(sensor); mSensorMap.add(sensor.getHandle(), s); mLastEventSeen.add(sensor.getHandle(), event);}
HardwareSensor实现了SensorInterface接口。
启动线程读取数据
调用run方法启动新线程,将调用SensorService::threadLoop()方法。
在新的线程中读取HAL层数据
SensorService实现了Thread类,当在onFirstRef中调用run方法的后,将在新的线程中调用SensorService::threadLoop()方法。
bool SensorService::threadLoop(){ …… do { count = device.poll(buffer, numEventMax); recordLastValue(buffer, count); …… const SortedVector< wp<SensorEventConnection> > activeConnections( getActiveConnections()); size_t numConnections = activeConnections.size(); for (size_t i=0 ; i<numConnections ; i++) { sp<SensorEventConnection> connection( activeConnections[i].promote()); if (connection != 0) { connection->sendEvents(buffer, count, scratch); } } } while (count >= 0 || Thread::exitPending()); return false;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
在while循环中一直读取HAL层数据,再调用SensorEventConnection->sendEvents将数据写到管道中。
客户端与服务端通信
数据传送
客户端服务端线程
在图中我们可以看到有两个线程,一个是服务端的一个线程,这个线程负责源源不断的从HAL读取数据。另一个是客户端的一个线程,客户端线程负责从消息队列中读数据。
创建消息队列
客户端可以创建多个消息队列,一个消息队列对应有一个与服务器通信的连接接口
创建连接接口
服务端与客户端沟通的桥梁,服务端读取到HAL层数据后,会扫面有多少个与客户端连接的接口,然后往每个接口的管道中写数据
创建管道
每一个连接接口都有对应的一个管道。
上面是设计者设计数据传送的原理,但是目前Android4.1上面的数据传送不能完全按照上面的理解。因为在实际使用中,消息队列只会创建一个,也就是说客户端与服务端之间的通信只有一个连接接口,只有一个管道传数据。那么数据的形式是怎么从HAL层传到JAVA层的呢?其实数据是以一个结构体sensors_event_t的形式从HAL层传到JNI层。看看HAL的sensors_event_t结构体:
typedef struct sensors_event_t { int32_t version; int32_t sensor; int32_t type; int32_t reserved0; int64_t timestamp; union { float data[16]; sensors_vec_t acceleration; sensors_vec_t magnetic; sensors_vec_t orientation; sensors_vec_t gyro; float temperature; float distance; float light; float pressure; float relative_humidity; }; uint32_t reserved1[4];} sensors_event_t;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
在JNI层有一个ASensorEvent结构体与sensors_event_t向对应,
frameworks/native/include/Android/sensor.h:
typedef struct ASensorEvent { int32_t version; int32_t sensor; int32_t type; int32_t reserved0; int64_t timestamp; union { float data[16]; ASensorVector vector; ASensorVector acceleration; ASensorVector magnetic; float temperature; float distance; float light; float pressure; }; int32_t reserved1[4];} ASensorEvent;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
在JNI层,只会将结构体数据中一部分的信息传到JAVA层:
经过前面的介绍,我们知道了客户端实现的方式及服务端的实现,但是没有具体讲到它两是如何进行通信的,这节我们专门介绍客户端与服务端之间的通信。
这里主要涉及的是进程间通信,有IBind和管道通信。客户端通过IBind通信获取到服务端的远程调用,然后通过管道进行sensor数据的传输。
管道是Linux 支持的最初Unix IPC形式之一,具有以下特点:
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。
服务端
native层实现了sensor服务的核心实现,Sensor服务的主要流程的实现在sensorservice类中,下面重点分析下这个类的流程。
class SensorService : public BinderService<SensorService>, public BnSensorServer, protected Thread
看看sensorService继承的类:
继承BinderService这个模板类添加到系统服务,用于Ibinder进程间通信。
template<typename SERVICE>class BinderService{public: static status_t publish() { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); } static void publishAndJoinThreadPool() { sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()), new SERVICE()); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } static void instantiate() { publish(); }};}; // namespace android
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
在前面的介绍中,SensorService服务的实例是在System_init.cpp中调用SensorService::instantiate()创建的,即调用了上面的instantiate()方法,接着调用了publish(),在该方法中,我们看到了new SensorService的实例,并且调用了defaultServiceManager::addService()将Sensor服务添加到了系统服务管理中,客户端可以通过defaultServiceManager:getService()获取到Sensor服务的实例。
继承BnSensorServer这个是sensor服务抽象接口类提供给客户端调用:
class Sensor;class ISensorEventConnection;class ISensorServer : public IInterface{public: DECLARE_META_INTERFACE(SensorServer); virtual Vector<Sensor> getSensorList() = 0; virtual sp<ISensorEventConnection> createSensorEventConnection() = 0;};class BnSensorServer : public BnInterface<ISensorServer>{public: //传输打包数据的通讯接口,在BnSensorServer被实现 virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);};};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
ISensorServer接口提供了两个抽象方法给客户端调用,关键在于
createSensorEventConnection()方法,该在服务端被实现,在客户端被调用,并返回一个SensorEventConnection的实例,创建连接,客户端拿到SensorEventConnection实例之后,可以对sensor进行通信操作,仅仅作为通信的接口而已,它并没有用来传送Sensor数据,因为Sensor数据量比较打,IBind实现比较困难。真正实现Sensor数据传送的是管道,在创建SensorEventConnection实例中,创建了BitTube对象,里面创建了管道,用于客户端与服务端的通信。
客户端
客户端主要在SensorManager.cpp中创建消息队列
class ISensorEventConnection;class Sensor;class Looper;class SensorEventQueue : public ASensorEventQueue, public RefBase{public: SensorEventQueue(const sp<ISensorEventConnection>& connection); virtual ~SensorEventQueue(); virtual void onFirstRef(); int getFd() const; static ssize_t write(const sp<BitTube>& tube, ASensorEvent const* events, size_t numEvents); ssize_t read(ASensorEvent* events, size_t numEvents); status_t waitForEvent() const; status_t wake() const; status_t enableSensor(Sensor const* sensor) const; status_t disableSensor(Sensor const* sensor) const; status_t setEventRate(Sensor const* sensor, nsecs_t ns) const; status_t enableSensor(int32_t handle, int32_t us) const; status_t disableSensor(int32_t handle) const;private:sp<Looper> getLooper() const;sp<ISensorEventConnection> mSensorEventConnection; sp<BitTube> mSensorChannel; mutable Mutex mLock; mutable sp<Looper> mLooper;};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
SensorEventQueue类作为消息队列,作用非常重要,在创建其实例的时候,传入了SensorEventConnection的实例,SensorEventConnection继承于ISensorEventConnection。SensorEventConnection其实是客户端调用SensorService的createSensorEventConnection()方法创建的,它是客户端与服务端沟通的桥梁,通过这个桥梁,可以完成一下任务:
获取管道的句柄
往管道读写数据
通知服务端对Sensor使能
流程解析
客户端获取SensorService服务实例
客户端初始化的时候,即SystemSensorManager的构造函数中,通过JNI调用,创建native层SensorManager的实例,然后调用SensorManager::assertStateLocked()方法做一些初始化的动作。
status_t SensorManager::assertStateLocked() const { if (mSensorServer == NULL) { const String16 name("sensorservice"); …… status_t err = getService(name, &mSensorServer); …… mSensors = mSensorServer->getSensorList(); size_t count = mSensors.size(); mSensorList = (Sensor const**)malloc(count * sizeof(Sensor*)); for (size_t i=0 ; i<count ; i++) { mSensorList[i] = mSensors.array() + i; } } return NO_ERROR;}
前面我们讲到过,SensorService的创建的时候调用了defaultServiceManager:getService()将服务添加到了系统服务管理中。现在我们又调用defaultServiceManager::geService()获取到SensorService服务的实例。在通过IBind通信,就可以获取到Sensor列表,所以在客户端初始化的时候,做了两件事情:
n 获取SensorService实例引用
n 获取Sensor传感器列表
创建消息队列
当客户端第一次注册监听器的时候,就需要创建一个消息队列,也就是说,android在目前的实现中,只创建了一个消息队列,一个消息队列中有一个管道,用于服务端与客户断传送Sensor数据。
在SensorManager.cpp中的createEventQueue方法创建消息队列:
sp<SensorEventQueue> SensorManager::createEventQueue(){ sp<SensorEventQueue> queue; Mutex::Autolock _l(mLock);while (assertStateLocked() == NO_ERROR) { sp<ISensorEventConnection> connection = mSensorServer->createSensorEventConnection(); if (connection == NULL) { LOGE("createEventQueue: connection is NULL. SensorService died."); continue; } queue = new SensorEventQueue(connection); break; } return queue;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
客户端与服务器创建一个SensorEventConnection连接接口,而一个消息队列中包含一个连接接口。
创建连接接口:
sp<ISensorEventConnection> SensorService::createSensorEventConnection(){ sp<SensorEventConnection> result(new SensorEventConnection(this)); return result;}SensorService::SensorEventConnection::SensorEventConnection( const sp<SensorService>& service) : mService(service), mChannel(new BitTube ()){}关键在于BitTube,在构造函数中创建了管道:BitTube::BitTube() : mSendFd(-1), mReceiveFd(-1){ int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) { int size = SOCKET_BUFFER_SIZE; setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); fcntl(sockets[0], F_SETFL, O_NONBLOCK); fcntl(sockets[1], F_SETFL, O_NONBLOCK); mReceiveFd = sockets[0]; mSendFd = sockets[1]; } else { mReceiveFd = -errno; ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd)); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
其中:fds[0]就是对应的mReceiveFd,是管道的读端,sensor数据的读取端,对应的是客户端进程访问的。fds[1]就是对应mSendFd,是管道的写端,sensor数据写入端,是sensor的服务进程访问的一端。通过pipe(fds)创建管道,通过fcntl来设置操作管道的方式,设置通道两端的操作方式为O_NONBLOCK ,非阻塞IO方式,read或write调用返回-1和EAGAIN错误。
总结下消息队列:
客户端第一次注册监听器的时候,就需要创建一个消息队列,客户端创了SensorThread线程从消息队列里面读取数据。
SensorEventQueue中有一个SensorEventConnection实例的引用,SensorEventConnection中有一个BitTube实例的引用。
使能Sensor
客户端创建了连接接口SensorEventConnection后,可以调用其方法使能Sensor传感器:
status_t SensorService::SensorEventConnection::enableDisable( int handle, bool enabled){ status_t err; if (enabled) { err = mService->enable(this, handle); } else { err = mService->disable(this, handle); } return err;}
handle对应着Sensor传感器的句柄
服务端往管道写数据
bool SensorService::threadLoop(){ …… do { count = device.poll(buffer, numEventMax); recordLastValue(buffer, count); …… const SortedVector< wp<SensorEventConnection> > activeConnections( getActiveConnections()); size_t numConnections = activeConnections.size(); for (size_t i=0 ; i<numConnections ; i++) { sp<SensorEventConnection> connection( activeConnections[i].promote()); if (connection != 0) { connection->sendEvents(buffer, count, scratch); } } } while (count >= 0 || Thread::exitPending()); return false;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
前面介绍过,在SensorService中,创建了一个线程不断从HAL层读取Sensor数据,就是在threadLoop方法中。关键在与下面了一个for循环,其实是扫描有多少个客户端连接接口,然后就往没每个连接的管道中写数据。
status_t SensorService::SensorEventConnection::sendEvents( sensors_event_t const* buffer, size_t numEvents, sensors_event_t* scratch){ size_t count = 0; if (scratch) { …… } …… if (count == 0) return 0; ssize_t size = mChannel->write(scratch, count*sizeof(sensors_event_t)); ……}
调用该连接接口的BitTube::write():
ssize_t BitTube::write(void const* vaddr, size_t size){ ssize_t err, len; do { len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL); err = len < 0 ? errno : 0; } while (err == EINTR); return err == 0 ? len : -err;} }
到此,服务端就完成了往管道的写端写入数据。
客户端读管道数据
ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents){ return BitTube::recvObjects(mSensorChannel, events, numEvents);}
调用到了BitTube::read():
static ssize_t recvObjects(const sp<BitTube>& tube, T* events, size_t count) { return recvObjects(tube, events, count, sizeof(T)); }ssize_t BitTube::recvObjects(const sp<BitTube>& tube, void* events, size_t count, size_t objSize){ ssize_t numObjects = 0; for (size_t i=0 ; i<count ; i++) { char* vaddr = reinterpret_cast<char*>(events) + objSize * i; ssize_t size = tube->read(vaddr, objSize); if (size < 0) { return size; } else if (size == 0) { break; } numObjects++; } return numObjects;}ssize_t BitTube::read(void* vaddr, size_t size){ ssize_t err, len; do { len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT); err = len < 0 ? errno : 0; } while (err == EINTR); if (err == EAGAIN || err == EWOULDBLOCK) { return 0; } return err == 0 ? len : -err;}
0 0