Step 36. ViewRoot.finishInputEvent

这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:

  1. publicfinalclassViewRootextendsHandlerimplementsViewParent,
  2. View.AttachInfo.Callbacks{
  3. ......
  4. privatevoidfinishInputEvent(){
  5. ......
  6. if(mFinishedCallback!=null){
  7. mFinishedCallback.run();
  8. mFinishedCallback=null;
  9. }else{
  10. ......
  11. }
  12. }
  13. ......
  14. }

ViewRoot类里面的成员变量mFinishedCallback是在前面Step 25中由InputQueue设置的,它是一个Runnable对象,实际类型是定义在InputQueue的内部类FinishedCallback,因此,这里调用它的run方法时,接下来就会调用InputQueue的内部类FinishedCallback的run成员函数:

  1. publicfinalclassInputQueue{
  2. ......
  3. privatestaticclassFinishedCallbackimplementsRunnable{
  4. ......
  5. publicvoidrun(){
  6. synchronized(sLock){
  7. ......
  8. nativeFinished(mFinishedToken);
  9. ......
  10. }
  11. }
  12. ......
  13. }
  14. ......
  15. }

这里它调用外部类InputQueue的本地方法nativeFinished来进一步处理。

Step 37. InputQueue.nativeFinished

这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:

  1. staticvoidandroid_view_InputQueue_nativeFinished(JNIEnv*env,jclassclazz,
  2. jlongfinishedToken){
  3. status_tstatus=gNativeInputQueue.finished(
  4. env,finishedToken,false/*ignoreSpuriousFinish*/);
  5. ......
  6. }
这个函数只是简单只调用NativeInputQueue的finished方法来进一处处理。

Step 38. NativeInputQueue.finished

这个函数定义在frameworks/base/core/jni/android_view_InputQueue.cpp文件中:

  1. status_tNativeInputQueue::finished(JNIEnv*env,jlongfinishedToken,boolignoreSpuriousFinish){
  2. int32_treceiveFd;
  3. uint16_tconnectionId;
  4. uint16_tmessageSeqNum;
  5. parseFinishedToken(finishedToken,&receiveFd,&connectionId,&messageSeqNum);
  6. {//acquirelock
  7. AutoMutex_l(mLock);
  8. ssize_tconnectionIndex=mConnectionsByReceiveFd.indexOfKey(receiveFd);
  9. ......
  10. sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);
  11. ......
  12. connection->messageInProgress=false;
  13. status_tstatus=connection->inputConsumer.sendFinishedSignal();
  14. ......
  15. }//releaselock
  16. returnOK;
  17. }
这个函数最重要的参数便是finishedToken了,通过它可以获得之前通知Java层的InputQueue类来处理键盘事件的Connection对象,它的值是在上面的Step 21(NativeInputQueue.handleReceiveCallback)中生成的:

  1. finishedToken=generateFinishedToken(receiveFd,connection->id,connection->messageSeqNum);

函数generateFinishedToken的定义如下:

  1. jlongNativeInputQueue::generateFinishedToken(int32_treceiveFd,uint16_tconnectionId,
  2. uint16_tmessageSeqNum){
  3. return(jlong(receiveFd)<<32)|(jlong(connectionId)<<16)|jlong(messageSeqNum);
  4. }

它的实现很简单,只是把receiveFd(前向管道的读端文件描述符)、connectionId(Client端的InputChannel对应的Connection对象在NativeInputQueue中的索引)和messageSeqNum(键盘消息的序列号)三个数值通过移位的方式编码在一个jlong值里面,即编码在上面的finishedToken参数里面。

因此,在上面的finished函数里面,首先就是要对参数值finishedToken进行解码,把receiveFd、connectionId和messageSeqNum三个值分别取回来:

  1. parseFinishedToken(finishedToken,&receiveFd,&connectionId,&messageSeqNum);

parseFinishedToken的定义如下:

  1. voidNativeInputQueue::parseFinishedToken(jlongfinishedToken,
  2. int32_t*outReceiveFd,uint16_t*outConnectionId,uint16_t*outMessageIndex){
  3. *outReceiveFd=int32_t(finishedToken>>32);
  4. *outConnectionId=uint16_t(finishedToken>>16);
  5. *outMessageIndex=uint16_t(finishedToken);
  6. }

有了这个receiveFd和connectionId之后,就可以把相应的Connection对象取回来了:

  1. ssize_tconnectionIndex=mConnectionsByReceiveFd.indexOfKey(receiveFd);
  2. ......
  3. sp<Connection>connection=mConnectionsByReceiveFd.valueAt(connectionIndex);

接下来就是调用这个connection对象中的inputConsumer对象来发送信号通知Server端的InputChannel,应用程序这一侧处理完刚才发生的键盘事件了:

  1. status_tstatus=connection->inputConsumer.sendFinishedSignal();

更多相关文章

  1. 引用自定义资源需注意数据类型
  2. Android下为自己定义WifiManager类wifi模块代码
  3. android Handlerr.removeCallbacksAndMessages(null)的妙用
  4. Android(安卓)SQLite存取图像
  5. unity 与 android 协调工作 注意事项
  6. 高斯模糊效果移植到android系统
  7. Android中findViewById返回为空null的快速解决办法
  8. Android应用程序键盘(Keyboard)消息处理机制分析(20)
  9. Android(安卓)P中如何自定义一个系统Service

随机推荐

  1. Android集成百度定位SDK实现获取定位地址
  2. Ubuntu下更新android sdk(sdk manager没有
  3. Android:解析JSON的三种方式
  4. MQTT——activemq5.8 推送消息实现
  5. Android(安卓)Studio高级使用详解
  6. Broadcast Receiver 的使用
  7. 在linux中配置usb连接
  8. 应用程序中捕获home按键事件
  9. [置顶] Android加载动态库失败分析
  10. Android(安卓)判断当前线程是否是主线程