Step 36. ViewRoot.finishInputEvent
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:
- public final class ViewRoot extends Handler implements ViewParent,
- View.AttachInfo.Callbacks {
- ......
- private void finishInputEvent() {
- ......
- if (mFinishedCallback != null) {
- mFinishedCallback.run();
- mFinishedCallback = null;
- } else {
- ......
- }
- }
- ......
- }
ViewRoot类里面的成员变量mFinishedCallback是在前面Step 25中由InputQueue设置的,它是一个Runnable对象,实际类型是定义在InputQueue的内部类FinishedCallback,因此,这里调用它的run方法时,接下来就会调用InputQueue的内部类FinishedCallback的run成员函数:
- public final class InputQueue {
- ......
- private static class FinishedCallback implements Runnable {
- ......
- public void run() {
- synchronized (sLock) {
- ......
- nativeFinished(mFinishedToken);
- ......
- }
- }
- ......
- }
- ......
- }
这里它调用外部类InputQueue的本地方法nativeFinished来进一步处理。
Step 37. InputQueue.nativeFinished
这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:
- static void android_view_InputQueue_nativeFinished(JNIEnv* env, jclass clazz,
- jlong finishedToken) {
- status_t status = gNativeInputQueue.finished(
- env, finishedToken, false /*ignoreSpuriousFinish*/);
- ......
- }
Step 38. NativeInputQueue.finished
这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:
- status_t NativeInputQueue::finished(JNIEnv* env, jlong finishedToken, bool ignoreSpuriousFinish) {
- int32_t receiveFd;
- uint16_t connectionId;
- uint16_t messageSeqNum;
- parseFinishedToken(finishedToken, &receiveFd, &connectionId, &messageSeqNum);
- { // acquire lock
- AutoMutex _l(mLock);
- ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
- ......
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- ......
- connection->messageInProgress = false;
- status_t status = connection->inputConsumer.sendFinishedSignal();
- ......
- } // release lock
- return OK;
- }
- finishedToken = generateFinishedToken(receiveFd, connection->id, connection->messageSeqNum);
函数generateFinishedToken的定义如下:
- jlong NativeInputQueue::generateFinishedToken(int32_t receiveFd, uint16_t connectionId,
- uint16_t messageSeqNum) {
- return (jlong(receiveFd) << 32) | (jlong(connectionId) << 16) | jlong(messageSeqNum);
- }
它的实现很简单,只是把receiveFd(前向管道的读端文件描述符)、connectionId(Client端的InputChannel对应的Connection对象在NativeInputQueue中的索引)和messageSeqNum(键盘消息的序列号)三个数值通过移位的方式编码在一个jlong值里面,即编码在上面的finishedToken参数里面。
因此,在上面的finished函数里面,首先就是要对参数值finishedToken进行解码,把receiveFd、connectionId和messageSeqNum三个值分别取回来:
- parseFinishedToken(finishedToken, &receiveFd, &connectionId, &messageSeqNum);
parseFinishedToken的定义如下:
- void NativeInputQueue::parseFinishedToken(jlong finishedToken,
- int32_t* outReceiveFd, uint16_t* outConnectionId, uint16_t* outMessageIndex) {
- *outReceiveFd = int32_t(finishedToken >> 32);
- *outConnectionId = uint16_t(finishedToken >> 16);
- *outMessageIndex = uint16_t(finishedToken);
- }
有了这个receiveFd和connectionId之后,就可以把相应的Connection对象取回来了:
- ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
- ......
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
接下来就是调用这个connection对象中的inputConsumer对象来发送信号通知Server端的InputChannel,应用程序这一侧处理完刚才发生的键盘事件了:
- status_t status = connection->inputConsumer.sendFinishedSignal();