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 );
-
- ......
- }
这个函数只是简单只调用NativeInputQueue的finished方法来进一处处理。
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);
-
- {
- AutoMutex _l(mLock);
-
- ssize_t connectionIndex = mConnectionsByReceiveFd.indexOfKey(receiveFd);
- ......
-
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- ......
-
- connection->messageInProgress = false;
-
- status_t status = connection->inputConsumer.sendFinishedSignal();
-
- ......
- }
-
- return OK;
- }
这个函数最重要的参数便是finishedToken了,通过它可以获得之前通知Java层的InputQueue类来处理键盘事件的Connection对象,它的值是在上面的Step 21(NativeInputQueue.handleReceiveCallback)中生成的:
- 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();
本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966645,如需转载请自行联系原作者