<pre name="code" class="cpp"><pre name="code" class="cpp">a
先上一张图,对input整体框架有个总体认识:
InputManager是输入控制中心,它有两个关键线程InputReaderThread和InputDispatcherThread,它们的主要功能部分分别在InputReader和InputDispacher。前者用于从设备中读取事件,后者将事件分发给目标窗口。EventHub是输入设备的控制中心,它直接与inputdriver打交道。负责处理输入设备的增减,查询,输入事件的处理并向上层提供getEvents()接口接收事件。在它的构造函数中,主要做三件事:
1. 创建epoll对象,之后就可以把各输入设备的fd挂在上面多路等待输入事件。
2. 建立用于唤醒的pipe,把读端挂到epoll上,以后如果有设备参数的变化需要处理,而getEvents()又阻塞在设备上,就可以调用wake()在pipe的写端写入,就可以让线程从等待中返回。
3. 利用inotify机制监听/dev/input目录下的变更,如有则意味着设备的变化,需要处理。
事件的处理是流水线,需要InputReader先读事件,然后InputDispatcher才能进一步处理和分发。因此InputDispatcher需要监听InputReader。这里使用了Listener模式,InputDispacher作为InputReader构造函数的第三个参数,它实现InputListenerInterface接口。到了InputReader的构造函数中,将之包装成QueuedInputListener。QueuedInputListener中的成员变量mArgsQueue是一个缓冲队列,只有在flush()时,才会一次性通知InputDispatcher。QueuedInputListener应用了Command模式(感觉更像观察者模式,这个设计模式待定),它通过包装InputDispatcher(实现InputListenerInterface接口),将事件的处理请求封装成NotifyArgs,使其有了缓冲执行的功能。
下面分析inputmanager的inputReader和InputDispatcher,分析后应该知道inputReader是怎么发送input事件给InputDispatcher,并且InputDispatcher是怎么把inut事件发送出去的。
先看一张序列图:
先分析inputReader:
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
....
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
if (count) {
processEventsLocked(mEventBuffer, count);
}
.....
mQueuedListener->flush();
}
这里只摘出了,我们需要分析的流程代码,EventHub先读取驱动中上报的input事件,然后再调用mQueueListener->flush()。
这个mQueueListener->flush()是什么东西?
这里用到了通知者模式:
进入InputListener.cpp查看代码可以看到,notifyXXXX,这里以notifyMotion举例说明,
void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
mArgsQueue.push(new NotifyMotionArgs(*args));
}
这里是实现了被通知者注册的函数,想要被通知方都可以注册,然后当通知方发送通知的时候,被通知方都能够收到消息。
被通知方类:
NotifyMotionArgs::NotifyMotionArgs(......) {
for (uint32_t i = 0; i < pointerCount; i++) {
this->pointerProperties[i].copyFrom(pointerProperties[i]);
this->pointerCoords[i].copyFrom(pointerCoords[i]);
}
}
NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other):.... {
for (uint32_t i = 0; i < pointerCount; i++) {
pointerProperties[i].copyFrom(other.pointerProperties[i]);
pointerCoords[i].copyFrom(other.pointerCoords[i]);
}
}
void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyMotion(this);
}
在哪里注册了这个NotifyMotionArgs?
void TouchInputMapper::dispatchMotion(){
.....
NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
action, flags, metaState, buttonState, edgeFlags,
mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
xPrecision, yPrecision, downTime);
getListener()->notifyMotion(&args);
}
这里就注册了被通知者,当然还有一些其他的被通知者类型,大家可以看InputListener.cpp文件。
QueuedInputListener::flush()函数的实现:
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
args->notify(mInnerListener);