Android应用程序键盘(Keyboard)消息处理机制分析(22)
Step 36. ViewRoot.finishInputEvent
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:
- publicfinalclassViewRootextendsHandlerimplementsViewParent,
- View.AttachInfo.Callbacks{
- ......
- privatevoidfinishInputEvent(){
- ......
- if(mFinishedCallback!=null){
- mFinishedCallback.run();
- mFinishedCallback=null;
- }else{
- ......
- }
- }
- ......
- }
ViewRoot类里面的成员变量mFinishedCallback是在前面Step 25中由InputQueue设置的,它是一个Runnable对象,实际类型是定义在InputQueue的内部类FinishedCallback,因此,这里调用它的run方法时,接下来就会调用InputQueue的内部类FinishedCallback的run成员函数:
- publicfinalclassInputQueue{
- ......
- privatestaticclassFinishedCallbackimplementsRunnable{
- ......
- publicvoidrun(){
- synchronized(sLock){
- ......
- nativeFinished(mFinishedToken);
- ......
- }
- }
- ......
- }
- ......
- }
这里它调用外部类InputQueue的本地方法nativeFinished来进一步处理。
Step 37. InputQueue.nativeFinished
这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:
- staticvoidandroid_view_InputQueue_nativeFinished(JNIEnv*env,jclassclazz,
- jlongfinishedToken){
- status_tstatus=gNativeInputQueue.finished(
- env,finishedToken,false/*ignoreSpuriousFinish*/);
- ......
- }
Step 38. NativeInputQueue.finished
这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:
- status_tNativeInputQueue::finished(JNIEnv*env,jlongfinishedToken,boolignoreSpuriousFinish){
- int32_treceiveFd;
- uint16_tconnectionId;
- uint16_tmessageSeqNum;
- parseFinishedToken(finishedToken,&receiveFd,&connectionId,&messageSeqNum);
- {//acquirelock
- AutoMutex_l(mLock);
- ssize_tconnectionIndex=mConnectionsByReceiveFd.indexOfKey(receiveFd);
- ......
- sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);
- ......
- connection->messageInProgress=false;
- status_tstatus=connection->inputConsumer.sendFinishedSignal();
- ......
- }//releaselock
- returnOK;
- }
- finishedToken=generateFinishedToken(receiveFd,connection->id,connection->messageSeqNum);
函数generateFinishedToken的定义如下:
- jlongNativeInputQueue::generateFinishedToken(int32_treceiveFd,uint16_tconnectionId,
- uint16_tmessageSeqNum){
- 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的定义如下:
- voidNativeInputQueue::parseFinishedToken(jlongfinishedToken,
- 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_tconnectionIndex=mConnectionsByReceiveFd.indexOfKey(receiveFd);
- ......
- sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);
接下来就是调用这个connection对象中的inputConsumer对象来发送信号通知Server端的InputChannel,应用程序这一侧处理完刚才发生的键盘事件了:
- status_tstatus=connection->inputConsumer.sendFinishedSignal();
更多相关文章
- C语言函数以及函数的使用
- 引用自定义资源需注意数据类型
- android 笔记 --- 自定义Android主题风格theme.xml方法
- Xposed框架之函数Hook学习
- anctionbar样式 自定义属性
- Android - GridView,自定义开关控件,状态选择器selector,自定义对话
- MPAndroidChart项目实战(七)——自定义横向柱状图
- android中自定义SeekBar