Android Native Looper机制 - 监听文件描述符
2015-07-19 11:25
603 查看
Navite Looper 除了提供message机制之外,还提供了监听文件描述符的方式。
通过addFd()接口加入需要被监听的文件描述符。
其中:
- fd:为所需要监听的文件描述符。
- ident:表示为当前发生事件的标识符,必须>=0,或者为POLL_CALLBACK(-2)如果指定了callback。
- events:表示为要监听的文件类型,默认是EVENT_INPUT。
- callback:当有事件发生时,会回调该callback函数。
- data: 两种使用方式:
指定callback来处理事件 : 当该文件描述符上有事件到来时,该callback会被执行,然后从该fd读取数据。这个时候ident是被忽略的。
通过指定的ident来处理事件: 当该文件描述符有数据到来时,pollOnce() 会返回一个ident,调用者会判断该ident是否等于自己需要处理的事件ident,如果是的话,则开始处理事件。
在Android 4.0.4版本SensorEventQueue.cpp 有使用。
SensorEventQueue.cpp : getLooper() : 将所需奥监听的文件描述符增加到looper中。
SensorEventQueue.cpp : waitForEvent(): 通过looper的pollOnce轮询监听事件,然后返回事件的标识符,如果事件的标识符等于getFd()所监听的文件描述符时,则返回NO_ERROR。
android/4.0.4/frameworks/base/core/jni/android_hardware_SensorManager.cpp : sensor_data_poll()
早期版本采用如下的消息驱动机制,在5.0版本已经没有这样使用了。
可以看到:当waitForEvent() 返回NO_ERROR,就会去读取数据。
实际上这种形式也是封装成了SimpleLooperCallback对象,该对象同样是继承自LooperCallback。
SimpleLooperCallback定义如下,在Looper.h 文件
通过addFd()接口加入需要被监听的文件描述符。
int addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data); int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data);
其中:
- fd:为所需要监听的文件描述符。
- ident:表示为当前发生事件的标识符,必须>=0,或者为POLL_CALLBACK(-2)如果指定了callback。
- events:表示为要监听的文件类型,默认是EVENT_INPUT。
- callback:当有事件发生时,会回调该callback函数。
- data: 两种使用方式:
指定callback来处理事件 : 当该文件描述符上有事件到来时,该callback会被执行,然后从该fd读取数据。这个时候ident是被忽略的。
通过指定的ident来处理事件: 当该文件描述符有数据到来时,pollOnce() 会返回一个ident,调用者会判断该ident是否等于自己需要处理的事件ident,如果是的话,则开始处理事件。
1. 通过指定的ident来处理事件:
使用场景:在Android 4.0.4版本SensorEventQueue.cpp 有使用。
SensorEventQueue.cpp : getLooper() : 将所需奥监听的文件描述符增加到looper中。
sp<Looper> SensorEventQueue::getLooper() const { Mutex::Autolock _l(mLock); if (mLooper == 0) { mLooper = new Looper(true); // 将要监听的文件描述符作为事件的标识符穿进去,并且callback为null mLooper->addFd(getFd(), getFd(), ALOOPER_EVENT_INPUT, NULL, NULL); } return mLooper; }
SensorEventQueue.cpp : waitForEvent(): 通过looper的pollOnce轮询监听事件,然后返回事件的标识符,如果事件的标识符等于getFd()所监听的文件描述符时,则返回NO_ERROR。
status_t SensorEventQueue::waitForEvent() const { const int fd = getFd(); sp<Looper> looper(getLooper()); int events; int32_t result; do { result = looper->pollOnce(-1, NULL, &events, NULL); if (result == ALOOPER_POLL_ERROR) { ALOGE("SensorEventQueue::waitForEvent error (errno=%d)", errno); result = -EPIPE; // unknown error, so we make up one break; } if (events & ALOOPER_EVENT_HANGUP) { // the other-side has died ALOGE("SensorEventQueue::waitForEvent error HANGUP"); result = -EPIPE; // unknown error, so we make up one break; } } while (result != fd); return (result == fd) ? status_t(NO_ERROR) : result; }
android/4.0.4/frameworks/base/core/jni/android_hardware_SensorManager.cpp : sensor_data_poll()
早期版本采用如下的消息驱动机制,在5.0版本已经没有这样使用了。
可以看到:当waitForEvent() 返回NO_ERROR,就会去读取数据。
static jint sensors_data_poll(JNIEnv *env, jclass clazz, jint nativeQueue, jfloatArray values, jintArray status, jlongArray timestamp) { sp<SensorEventQueue> queue(reinterpret_cast<SensorEventQueue *>(nativeQueue)); if (queue == 0) return -1; status_t res; ASensorEvent event; res = queue->read(&event, 1); if (res == -EAGAIN) { res = queue->waitForEvent(); if (res != NO_ERROR) return -1; res = queue->read(&event, 1); } if (res < 0) return -1; jint accuracy = event.vector.status; env->SetFloatArrayRegion(values, 0, 3, event.vector.v); env->SetIntArrayRegion(status, 0, 1, &accuracy); env->SetLongArrayRegion(timestamp, 0, 1, &event.timestamp); return event.sensor; }
2. 指定callback来处理事件:
callback 必须是继承子LooperCallback,或者是如下形式的回调函数。typedef int (*Looper_callbackFunc)(int fd, int events, void* data);
实际上这种形式也是封装成了SimpleLooperCallback对象,该对象同样是继承自LooperCallback。
int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) { return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data); }
SimpleLooperCallback定义如下,在Looper.h 文件
/** * Wraps a Looper_callbackFunc function pointer. */ class SimpleLooperCallback : public LooperCallback { protected: virtual ~SimpleLooperCallback(); public: SimpleLooperCallback(Looper_callbackFunc callback); virtual int handleEvent(int fd, int events, void* data); private: Looper_callbackFunc mCallback; };
使用场景1:
InputDispatcher.cpp : registerInputChannel() mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); handleReceiveCallback() 的实现如下: int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { InputDispatcher* d = static_cast<InputDispatcher*>(data); ...
使用场景2:
android_view_InputEventReceiver.cpp : setFdEvents() 将fd加入looper 轮询监听,另外还需要实现一个handleEvent() 函数。void NativeInputEventReceiver::setFdEvents(int events) { if (mFdEvents != events) { mFdEvents = events; int fd = mInputConsumer.getChannel()->getFd(); if (events) { mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL); } else { mMessageQueue->getLooper()->removeFd(fd); } } } int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) { if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { ...
相关文章推荐
- [M0]Android Native层Looper详解
- Android onClick 按钮单击事件 四种常用写法
- android下拉刷新之PullToRefreshListView(二)
- Asynctask使用小结
- Android Studio使用技巧
- android自定义button样式
- Android 四大组件学习之Activity三
- Android 之 ServiceManager与服务管理
- Android binder driver 分析
- Android 四大组件学习之Activity二
- Android中handler的使用及原理---学习笔记
- Android中handler的使用及原理---学习笔记
- Day04-SmartImageView
- MPAndroidChart开源图表库之折线图
- Android View深入学习(三),View的绘制(Draw)过程
- Android中实现版本更新(一)使用第三方sdk更新
- Android之——AsyncTask和Handler对比
- android中ProgressBar和ListView
- Android Binder- 一次完整的通信过程
- Android 四大组件学习之Activity一