Sensor整體架構
整體架構說明
- 黃色部分表示硬件,它要掛在I2C總線上
- 紅色部分表示驅動,驅動注冊到Kernel的Input Subsystem上,然后通過Event Device把Sensor數據傳到HAL層,准確說是HAL從Event讀
- 綠色部分表示動態庫,它封裝了整個Sensor的IPC機制,如SensorManager是客戶端,SensorService是服務端,而HAL部分是封裝了服務端對Kernel的直接訪問
- 藍色部分就是我們的Framework和Application了,JNI負責訪問Sensor的客戶端,而Application就是具體的應用程序,用來接收Sensor返回的數據,並處理實現對應的UI效果,如屏幕旋轉,打電話時滅屏,自動調接背光(這三個功能的具體實現會在以后分析)
Sensor總體調用關系圖
本節主要解讀Android的Framework層框架。
Sensor 框架分為三個層次,客戶度、服務端、HAL層,服務端負責從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讀取數據
HAL層
Sensor.h是google為Sensor定義的Hal接口,單獨提出去
客戶端讀取數據
調用時序圖
apk注冊監聽器

SensorManager mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); Sensor mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); protected void onResume() { super.onResume(); mSensorManager. registerListenerImpl (this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); } protected void onPause() { super.onPause(); mSensorManager.unregisterListener(this); } public interface SensorEventListener { public void onSensorChanged(SensorEvent event); public void onAccuracyChanged(Sensor sensor, int accuracy); }
Activity實現了SensorEventListener接口。
在onCreate方法中,獲取SystemSensorManager,並獲取到加速傳感器的Sensor;
在onResume方法中調用SystemSensorManager,registerListenerImpl注冊監聽器;
當Sensor數據有改變的時候將會回調onSensorChanged方法。
初始化SystemSensorManager

public SystemSensorManager(Context context,Looper mainLooper) { mMainLooper = mainLooper; mContext = context; synchronized(sListeners) { if (!sSensorModuleInitialized) { sSensorModuleInitialized = true; nativeClassInit(); // initialize the sensor list 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) { //Log.d(TAG, "found sensor: " + sensor.getName() + // ", handle=" + sensor.getHandle()); fullList.add(sensor); sHandleToSensor.append(sensor.getHandle(), sensor); } } while (i>0); sPool = new SensorEventPool( sFullSensorsList.size()*2 ); sSensorThread = new SensorThread(); } } }
系統開機啟動的時候,會創建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 we don't find it, add it to the list 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; }
當有應用程序調用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); ……. } } }
在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) { // Start the sensor service 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); } } } }
這里主要做了三個工作:
- 調用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]) ); …… } // it's safe to instantiate the SensorFusion object here // (it wants to be instantiated after h/w sensors have been // registered) const SensorFusion& fusion(SensorFusion::getInstance()); if (hasGyro) { …… } …… run("SensorService", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; } } }
在這個方法中,主要做了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()); // 添加到Sensor列表,給客戶端使用 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); }
HardwareSensor實現了SensorInterface接口。
- 啟動線程讀取數據
調用run方法啟動新線程,將調用SensorService::threadLoop()方法。
在新的線程中讀取HAL層數據
SensorService實現了Thread類,當在onFirstRef中調用run方法后,將在新的線程中調用SensorService::threadLoop()方法。

bool SensorService::threadLoop() { …… do { count = device.poll(buffer, numEventMax); recordLastValue(buffer, count); …… // send our events to clients... 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; }
在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;
在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;
交互調用時序圖
經過前面的介紹,現在知道了客戶端實現的方式及服務端的實現,但是沒有具體講到它們是如何進行通信的,現在看看客戶端與服務端之間的通信。
主要涉及的是進程間通信,有IBind和管道通信。
客戶端通過IBind通信獲取到服務端的遠程調用,然后通過管道進行sensor數據的傳輸。
服務端
native層實現了sensor服務的核心實現,Sensor服務的主要流程的實現在sensorservice類中,下面重點分析下這個類的流程。

class SensorService : public BinderService<SensorService>, public BnSensorServer, protected Thread
看看sensorService繼承的類:
繼承BinderService<SensorService>這個模板類添加到系統服務,用於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
在前面的介紹中,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); //獲取Sensor列表 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); }; }; // namespace android
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; //使能Sensor傳感器 status_t enableSensor(Sensor const* sensor) const; status_t disableSensor(Sensor const* sensor) const; status_t setEventRate(Sensor const* sensor, nsecs_t ns) const; // these are here only to support SensorManager.java status_t enableSensor(int32_t handle, int32_t us) const; status_t disableSensor(int32_t handle) const; private: sp<Looper> getLooper() const; //連接接口,在SensorService中創建的 sp<ISensorEventConnection> mSensorEventConnection; //管道指針 sp<BitTube> mSensorChannel; mutable Mutex mLock; mutable sp<Looper> mLooper; };
SensorEventQueue類作為消息隊列,作用非常重要,在創建其實例的時候,傳入了SensorEventConnection的實例,SensorEventConnection繼承於ISensorEventConnection。
SensorEventConnection其實是客戶端調用SensorService的createSensorEventConnection()方法創建的,它是客戶端與服務端溝通的橋梁,通過這個橋梁,可以完成一下任務:
- 獲取管道的句柄
- 往管道讀寫數據
- 通知服務端對Sensor使能
流程解析
客戶端獲取SensorService服務實例
客戶端初始化的時候,即SystemSensorManager的構造函數中,通過JNI調用,創建native層SensorManager的實例,然后調用SensorManager::assertStateLocked()方法做一些初始化的動作。

status_t SensorManager::assertStateLocked() const { if (mSensorServer == NULL) { // try for one second 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列表,所以在客戶端初始化的時候,做了兩件事情:
- 獲取SensorService實例引用
- 獲取Sensor傳感器列表
注冊SensorLisenter
時序圖
new ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler)
在這個構造函數中會創建一個Handler,它會在獲取到Sensor數據的時候被調用。

mHandler = new Handler(looper) { @Override public void handleMessage(Message msg) { final SensorEvent t = (SensorEvent)msg.obj; final int handle = t.sensor.getHandle(); switch (t.sensor.getType()) { // Only report accuracy for sensors that support it. case Sensor.TYPE_MAGNETIC_FIELD: case Sensor.TYPE_ORIENTATION: // call onAccuracyChanged() only if the value changes final int accuracy = mSensorAccuracies.get(handle); if ((t.accuracy >= 0) && (accuracy != t.accuracy)) { mSensorAccuracies.put(handle, t.accuracy); mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy); } break; default: // For other sensors, just report the accuracy once if (mFirstEvent.get(handle) == false) { mFirstEvent.put(handle, true); mSensorEventListener.onAccuracyChanged( t.sensor, SENSOR_STATUS_ACCURACY_HIGH); } break; } mSensorEventListener.onSensorChanged(t); sPool.returnToPool(t); } };
創建消息隊列
時序圖
當客戶端第一次注冊監聽器的時候,就需要創建一個消息隊列,也就是說,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) { // SensorService just died. LOGE("createEventQueue: connection is NULL. SensorService died."); continue; } //創建消息隊列 queue = new SensorEventQueue(connection); break; } return queue; }
客戶端與服務器創建一個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)); } }
其中: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); …… // send our events to clients... 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; }
前面介紹過,在SensorService中,創建了一個線程不斷從HAL層讀取Sensor數據,就是在threadLoop方法中。
關鍵在與下面了一個for循環,其實是掃描有多少個客戶端連接接口,然后就往沒每個連接的管道中寫數據。

status_t SensorService::SensorEventConnection::sendEvents( sensors_event_t const* buffer, size_t numEvents, sensors_event_t* scratch) { // filter out events not for this connection 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) { // error occurred return size; } else if (size == 0) { // no more messages 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; }
參考文章
http://blog.sina.com.cn/u/2314572533
http://blog.csdn.net/cs_lht