接着上篇文章Android IMS原理解析之InputChannel,上篇文章讲到,当有事件到来时,触发NativeInputEventReceiver的回调接下来会调用到Java层InputEventReceiver的方法,看一下Java层的事件处理:
Input事件处理
前面分析到事件已经发送到对应的窗口了,接下来就是事件的处理流程,从onInputEvent()来开始分析:
final class WindowInputEventReceiver extends InputEventReceiver {
@Override
public void onInputEvent(InputEvent event, int displayId) {
enqueueInputEvent(event, this, 0, true);
}
}
在onInputEvent()内部会执行enqueueInputEvent(),传入了this及InputEvent等参数,接下来看一下enqueueInputEvent():
void enqueueInputEvent(InputEvent event,InputEventReceiver receiver, int flags, boolean processImmediately) {
adjustInputEventForCompatibility(event);
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
mPendingInputEventCount += 1;
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
该方法内部执行执行三项工作:
1.通过obtainQueuedInputEvent()来获取QueuedInputEvent实例,对InputEvent进行封装,类似Message处理;
2.对mPendingInputEventTail及mPendingInputEventTail进相关的处理,接下来事件处理会用到;
3.由于processImmediately为true,因此执行doProcessInputEvents()进行逻辑处理;
接下来对以上三项工作进行一一分析:
private QueuedInputEvent obtainQueuedInputEvent(InputEvent event,
InputEventReceiver receiver, int flags) {
QueuedInputEvent q = mQueuedInputEventPool;
if (q != null) {
mQueuedInputEventPoolSize -= 1;
mQueuedInputEventPool = q.mNext;
q.mNext = null;
} else {
q = new QueuedInputEvent();
}
q.mEvent = event;
q.mReceiver = receiver;
q.mFlags = flags;
return q;
}
从obtainQueuedInputEvent()可以看到,执行逻辑跟obtainMessage逻辑是一致的,先从pool里面取,如果没有的话就重新创建,然后进行赋值,对比messgae的处理逻辑,也有对应的recycle方法:
private void recycleQueuedInputEvent(QueuedInputEvent q) {
q.mEvent = null;
q.mReceiver = null;
if (mQueuedInputEventPoolSize < MAX_QUEUED_INPUT_EVENT_POOL_SIZE) {
mQueuedInputEventPoolSize += 1;
q.mNext = mQueuedInputEventPool;
mQueuedInputEventPool = q;
}
}
mQueuedInputEventPool赋值是在recycleQueuedInputEvent()内部,pool Size最大为10,超过后就不处理了。
第二项工作是赋值操作,是为第三项工作做准备的,直接看第三项工作doProcessInputEvents():
void doProcessInputEvents() {
// Deliver all pending input events in the queue.
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;
mPendingInputEventCount -= 1;
......
deliverInputEvent(q);
}
.....
}
在doProcessInputEvents()内部最终执行了deliverInputEvent(q):
private void deliverInputEvent(QueuedInputEvent q) {
.....
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
在deliverInputEvent()内部会执行InputStage的deliver()方法,stage是在setView()中进行赋值的,此处对应的是ViewPostImeInputStage,一起看一下:
abstract class InputStage {
......
public final void deliver(QueuedInputEvent q) {
if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
forward(q);
} else if (shouldDropInputEvent(q)) {
finish(q, false);
} else {
apply(q, onProcess(q));
}
}
protected void apply(QueuedInputEvent q, int result) {
if (result == FORWARD) {
forward(q);
} else if (result == FINISH_HANDLED) {
finish(q, true);
} else if (result == FINISH_NOT_HANDLED) {
finish(q, false);
} else {
throw new IllegalArgumentException("Invalid result: " + result);
}
}
.....
}
final class ViewPostImeInputStage extends InputStage {
......
@Override
protected int onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) {
return processKeyEvent(q);
} else {
final int source = q.mEvent.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
return processPointerEvent(q);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
return processTrackballEvent(q);
} else {
return processGenericMotionEvent(q);
}
}
}
......
}
可以看到,在执行deliver()时会执行apply(),然后执行onProcess(),在onProcess()内部来选择执行processKeyEvent()或processPointerEvent()[在其内部将Event传递到对应的目标控件,后面进行分析]来对事件进行处理,在处理完后针对不同的返回result来调用finish()-->forward()-->onDeliverToNext()[mNext不null,继续deliver;为null]-->finishInputEvent()来发送事件结束信息到InputDispatcher进行接下来的处理工作,看一下finishInputEvent()方法实现:
private void finishInputEvent(QueuedInputEvent q) {
if (q.mReceiver != null) {
boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
q.mReceiver.finishInputEvent(q.mEvent, handled);
} else {
q.mEvent.recycleIfNeededAfterDispatch();
}
recycleQueuedInputEvent(q);
}
q.mReceiver是在obtainQueuedInputEvent()时传入的是InputEventReceiver对象,因此调用的是InputEventReceiver的finishInputEvent(),然后执行recycleQueuedInputEvent(q)来回收QueuedInputEvent ,前面已经分析过,逻辑跟Message处理是一致的,此处用的是享元模式;接下来看一下InputEventReceiver的finishInputEvent()方法:
public final void finishInputEvent(InputEvent event, boolean handled) {
......
int index = mSeqMap.indexOfKey(event.getSequenceNumber());
int seq = mSeqMap.valueAt(index);
mSeqMap.removeAt(index);
nativeFinishInputEvent(mReceiverPtr, seq, handled);
}
从mSeqMap里面取出对应的seq,然后执行nativeFinishInputEvent(),mReceiverPtr是在nativeInit时返回的NativeInputEventReceiver对象引用,一起去native层去看一下nativeFinishInputEvent()的具体实现:
static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
jint seq, jboolean handled) {
sp receiver =
reinterpret_cast(receiverPtr);
status_t status = receiver->finishInputEvent(seq, handled);
}
调用的是NativeInputEventReceiver的finishInputEvent():
status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
......
return status;
}
接着通过InputConsumer的sendFinishedSignal()来进行发送:
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
......
return sendUnchainedFinishedSignal(seq, handled);
......
}
最终是通过mChannel来进行发送;
status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
InputMessage msg;
msg.header.type = InputMessage::TYPE_FINISHED;
msg.body.finished.seq = seq;
msg.body.finished.handled = handled;
return mChannel->sendMessage(&msg);
}
前面讲到在addView()时执行registerInputChannel()时会在InputDispatcher里面通过mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this)注册了对InputChannel fd的监听,当有可读消息时,会回调handleReceiveCallback()方法:
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
InputDispatcher* d = static_cast(data);
{ // acquire lock
AutoMutex _l(d->mLock);
ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
bool notify;
//根据可读的InputChannel的描述符获取对应的Connection对象
sp connection = d->mConnectionsByFd.valueAt(connectionIndex);
nsecs_t currentTime = now();
bool gotOne = false;
status_t status;
for (;;) {
uint32_t seq;
bool handled;
//在循环中不断地读取尽可能多的反馈信息
status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
if (status) {
break;
}
//调用finishDispatchCycleLocked()函数完成对反馈的处理
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
gotOne = true;
}
if (gotOne) {
d->runCommandsLockedInterruptible();
if (status == WOULD_BLOCK) {
return 1;
}
}
}
// Unregister the channel.
d->unregisterInputChannelLocked(connection->inputChannel, notify);
return 0; // remove the callback
} // release lock
}
finishDispatchCycleLocked()函数只是将向InputDispatcher发送一个命令。最终处理反馈的函数是doDispatchCycleFinishedLockedInterruptible(),本文就不详细介绍了,到此一个事件就算闭环了。
用一张图来总结一下处理及反馈过程:
本文只从整体上分析了事件的处理及反馈过程,对processKeyEvent()及processPointerEvent()的详细介绍请参考下一篇文章Android IMS原理解析之dispatchEvent