Android输入系统之InputChannel(下)

Client 对输入事件处理

          输入事件,比如按键事件并不是全部被window的view处理了,比如Back键,如果此时系统输入法是显示的,其实该键首先会去关闭输入法,而window的view是接收不到这个键的,这个就是事件处理器链实现的,这个链上又各种处理器,它们按照处理的优先顺序添加咋链表上

输入事件处理链

    
[java] view plain copy
  1. public abstract class InputEventReceiver {  
  2.     //native收到输入事件是最终会回调到该函数  
  3.     private void dispatchInputEvent(int seq, InputEvent event) {  
  4.         mSeqMap.put(event.getSequenceNumber(), seq);  
  5.         onInputEvent(event);  
  6.     }  
  7. }  
  8.   
  9.    final class WindowInputEventReceiver extends InputEventReceiver {  
  10.         @Override  
  11.         public void onInputEvent(InputEvent event) {  
  12.             enqueueInputEvent(event, this0true);  
  13.         }  
  14.     }  
  15.   
  16.     void enqueueInputEvent(InputEvent event) {  
  17.         enqueueInputEvent(event, null0false);  
  18.     }  
  19.   
  20.     void enqueueInputEvent(InputEvent event,  
  21.             InputEventReceiver receiver, int flags, boolean processImmediately) {  
  22.         QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);  
  23.         QueuedInputEvent last = mPendingInputEventTail;  
  24.         if (last == null) {  
  25.             mPendingInputEventHead = q;  
  26.             mPendingInputEventTail = q;  
  27.         } else {  
  28.             last.mNext = q;  
  29.             mPendingInputEventTail = q;  
  30.         }  
  31.         mPendingInputEventCount += 1;  
  32.         if (processImmediately) {  
  33.             //处理事件  
  34.             doProcessInputEvents();  
  35.         } else {  
  36.             scheduleProcessInputEvents();  
  37.         }  
  38.     }  
  39.   
  40.     void doProcessInputEvents() {  
  41.         // 遍历所有的输入事件  
  42.         while (mPendingInputEventHead != null) {  
  43.             QueuedInputEvent q = mPendingInputEventHead;  
  44.             mPendingInputEventHead = q.mNext;  
  45.             if (mPendingInputEventHead == null) {  
  46.                 mPendingInputEventTail = null;  
  47.             }  
  48.             q.mNext = null;  
  49.   
  50.             mPendingInputEventCount -= 1;  
  51.             //处理事件  
  52.             deliverInputEvent(q);  
  53.         }  
  54.     }  
  55.   
  56.     private void deliverInputEvent(QueuedInputEvent q) {  
  57.         try {  
  58.             //检测ime相关module是否需要处理该输入事件,比如back键,是需要先  
  59.             //让IME处理,这个时候需要先交给mFirstPostImeInputStage处理  
  60.             InputStage stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;  
  61.             if (stage != null) {  
  62.                 stage.deliver(q);  
  63.             } else {  
  64.                 //  
  65.                 finishInputEvent(q);  
  66.             }  
  67.         }  
  68.     }  
  69.   
  70.        //大部分时候stage= mFirstInputStage,这个变量在最开始的时候赋值  
  71.        InputStage syntheticInputStage = new SyntheticInputStage();  
  72.        InputStage viewPostImeStage = new ViewPostImeInputStage(syntheticInputStage);  
  73.        InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,  
  74.                   "aq:native-post-ime:" + counterSuffix);  
  75.        InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);  
  76.        InputStage imeStage = new ImeInputStage(earlyPostImeStage,  
  77.                         "aq:ime:" + counterSuffix);  
  78.        InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);  
  79.        InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,  
  80.                         "aq:native-pre-ime:" + counterSuffix);  
  81.        mFirstInputStage = nativePreImeStage;  
  82.        mFirstPostImeInputStage = earlyPostImeStage;<div>  
  83.        abstract class InputStage {  
  84.         public final void deliver(QueuedInputEvent q) {  
  85.             if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {  
  86.                 //已经被处理了,则让后面的处理  
  87.                 forward(q);  
  88.             } else if (shouldDropInputEvent(q)) {  
  89.                 finish(q, false);  
  90.             } else {  
  91.                 //没有处理,自己开始处理该事件  
  92.                 apply(q, onProcess(q));  
  93.             }  
  94.         }  
  95.           
  96.         protected void apply(QueuedInputEvent q, int result) {  
  97.             if (result == FORWARD) {  
  98.                 forward(q);  
  99.             } else if (result == FINISH_HANDLED) {  
  100.                 finish(q, true);  
  101.             }  
  102.         }  
  103.   
  104.         protected void forward(QueuedInputEvent q) {  
  105.             onDeliverToNext(q);  
  106.         }  
  107.   
  108.         protected void onDeliverToNext(QueuedInputEvent q) {  
  109.             //如果下一个事件处理器不为空,则让下一个事件处理器处理  
  110.             if (mNext != null) {  
  111.                 mNext.deliver(q);  
  112.             } else {  
  113.                //所有的都处理器都完成了处理,调用finish告知server端事件已经被处理  
  114.                 finishInputEvent(q);  
  115.             }  
  116.         }  
  117. }  
  118.   
  119.     //将事件发送给view的事件处理器是ViewPostImeInputStage  
  120.     final class ViewPostImeInputStage extends InputStage {  
  121.         @Override  
  122.         protected int onProcess(QueuedInputEvent q) {  
  123.             if (q.mEvent instanceof KeyEvent) {  
  124.                 return processKeyEvent(q);  
  125.             }  
  126.         }  
  127.   
  128.         private int processKeyEvent(QueuedInputEvent q) {  
  129.             final KeyEvent event = (KeyEvent)q.mEvent;  
  130.   
  131.             if (event.getAction() != KeyEvent.ACTION_UP) {  
  132.                 // If delivering a new key event, make sure the window is  
  133.                 // now allowed to start updating.  
  134.                 handleDispatchDoneAnimating();  
  135.             }  
  136.   
  137.             // 向view发送按键事件  
  138.             if (mView.dispatchKeyEvent(event)) {  
  139.                 return FINISH_HANDLED;  
  140.             }  
  141.   
  142.             // 系统默认按键处理,比如CAMERA快捷键处理  
  143.             if (mFallbackEventHandler.dispatchKeyEvent(event)) {  
  144.                 return FINISH_HANDLED;  
  145.             }  
  146.             return FORWARD;  
  147.         }  
  148.     }   


        从上面的逻辑可以看出处理器的处理有限顺序是:

NativePreImeInputStage->ViewPreImeInputStage-> ImeInputStage->

EarlyPostImeInputStage-> NativePostImeInputStage->ViewPostImeInputStage->

SyntheticInputStage

 

Back按键如何结束Activity

         刚刚前面说到,view获得输入事件是由ViewPostImeInputStage传递过来的。ViewPostImeInputStage会将事件传递给activity的根View ---DecorView

        

[java] view plain copy
  1.    private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {  
  2.         @Override  
  3.         public boolean dispatchKeyEvent(KeyEvent event) {  
  4.             if (!isDestroyed()) {  
  5.                 //首先让callback处理,然后调用super的接口  
  6.                 final Callback cb = getCallback() && mFeatureId < 0 ?   
  7. cb.dispatchKeyEvent(event)  
  8.                         : super.dispatchKeyEvent(event);  
  9.                 if (handled) {  
  10.                     return true;  
  11.                 }  
  12.             }  
  13.   
  14.             return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)  
  15.                     : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);  
  16.         }  
  17.    }  
  18.   
  19.    //上面的getCallback的返回值就是Activity,故其有很高的优先级获取并处理这些按键。  
  20.    public boolean onKeyDown(int keyCode, KeyEvent event)  {  
  21.         if (keyCode == KeyEvent.KEYCODE_BACK) {  
  22.             if (getApplicationInfo().targetSdkVersion  
  23.                     >= Build.VERSION_CODES.ECLAIR) {  
  24.             } else {  
  25.                 //这个就是结束activity的函数  
  26.                 onBackPressed();  
  27.             }  
  28.             return true;  
  29.         }  
  30.     }  

        如果非back按键,则会调用super即View.dispatchKeyEvent的接口,view的事件接收及处理就是从这开始的。

View如何获取按键

         由于DecorView继承FrameLayout,它自然是一个ViewGroup,所以我们来看下ViewGroup的dispatchKeyEvent。

[java] view plain copy
  1. @Override  
  2. public boolean dispatchKeyEvent(KeyEvent event) {  
  3.     if (mInputEventConsistencyVerifier != null) {  
  4.         mInputEventConsistencyVerifier.onKeyEvent(event, 1);  
  5.     }  
  6.   
  7.     if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))  
  8.             == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {  
  9.         //调用view的接口  
  10.         if (super.dispatchKeyEvent(event)) {  
  11.             return true;  
  12.         }  
  13.     } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)  
  14.             == PFLAG_HAS_BOUNDS) {  
  15.         //向获得焦点的view传递事件  
  16.         if (mFocused.dispatchKeyEvent(event)) {  
  17.             return true;  
  18.         }  
  19.     }  
  20.     return false;  
  21. }  
  22.   
  23. public boolean dispatchKeyEvent(KeyEvent event) {  
  24.     if (event.dispatch(this, mAttachInfo != null  
  25.             ? mAttachInfo.mKeyDispatchState : nullthis)) {  
  26.         return true;  
  27.     }  
  28.     return false;  
  29. }  
  30.   
  31. public final boolean dispatch(Callback receiver, DispatcherState state,  
  32.         Object target) {  
  33.     switch (mAction) {  
  34.         case ACTION_DOWN: {  
  35.             mFlags &= ~FLAG_START_TRACKING;  
  36.             //这个就是我们的常见的onKeyDown,onKeyUp接口的调用  
  37.             boolean res = receiver.onKeyDown(mKeyCode, this);  
  38.             return res;  
  39.         }  
  40.     }  
  41.     return false;  
  42. }  


Camera等快捷键是如何传递处理的

         如果view没有处理按键,则最后会给mFallbackEventHandler一个机会处理按键,Camera等快捷键就是由这个handler处理的,下面来看看。

         

[java] view plain copy
  1. public ViewRootImpl(Context context, Display display) {         
  2. mFallbackEventHandler= PolicyManager.makeNewFallbackEventHandler(context);  
  3. }  
  4.   
  5. public class Policy implements IPolicy {  
  6. public FallbackEventHandler makeNewFallbackEventHandler(Context context) {  
  7.    return new PhoneFallbackEventHandler(context);  
  8. }  
  9. }  
  10.   
  11. public class PhoneFallbackEventHandler implements FallbackEventHandler {  
  12.     public boolean dispatchKeyEvent(KeyEvent event) {  
  13.   
  14.         final int action = event.getAction();  
  15.         final int keyCode = event.getKeyCode();  
  16.   
  17.         if (action == KeyEvent.ACTION_DOWN) {  
  18.             return onKeyDown(keyCode, event);  
  19.         } else {  
  20.             return onKeyUp(keyCode, event);  
  21.         }  
  22.     }  
  23.       
  24.     boolean onKeyDown(int keyCode, KeyEvent event) {  
  25.         switch (keyCode) {  
  26.             case KeyEvent.KEYCODE_CAMERA: {  
  27.                 if (event.getRepeatCount() == 0) {  
  28.                 } else if (event.isLongPress() && dispatcher.isTracking(event)) {  
  29.                     //启动拍照程序  
  30.                     Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);  
  31.                     intent.putExtra(Intent.EXTRA_KEY_EVENT, event);  
  32.                     mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF,  
  33.                             nullnullnull0nullnull);  
  34.                 }  
  35.                 return true;  
  36.             }  
  37.         }  
  38.         return false;  
  39.     }  

输入事件处理完成通知

       client将事件处理完了,必须通知server已经完成对该事件的处理,否则server一直在等待事件完成而不能发送后面的事件。

[java] view plain copy
  1. private void finishInputEvent(QueuedInputEvent q) {  
  2.         if (q.mReceiver != null) {  
  3.             boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;                
  4.             // mReceiver是InputEventReciever  
  5.             q.mReceiver.finishInputEvent(q.mEvent, handled);  
  6.         }  
  7.         recycleQueuedInputEvent(q);  
  8. }  
  9.   
  10. public abstract class InputEventReceiver {  
  11.     public final void finishInputEvent(InputEvent event, boolean handled) {  
  12.         {  
  13.             int index = mSeqMap.indexOfKey(event.getSequenceNumber());  
  14.             if (index < 0) {  
  15.             } else {  
  16.                 //又调回native层  
  17.                 nativeFinishInputEvent(mReceiverPtr, seq, handled);  
  18.             }  
  19.         }  
  20.         event.recycleIfNeededAfterDispatch();  
  21.     }  
  22. }  
  23.   
  24.   
  25. status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {  
  26.     //告知server端client已经处理完成inputEvent  
  27.     status_t status = mInputConsumer.sendFinishedSignal(seq, handled);  
  28.     return status;  
  29. }  
  30.   
  31.   
  32. status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {  
  33.     size_t seqChainCount = mSeqChains.size();  
  34.     if (seqChainCount) {  
  35.         uint32_t currentSeq = seq;  
  36.         uint32_t chainSeqs[seqChainCount];  
  37.         size_t chainIndex = 0;  
  38.         for (size_t i = seqChainCount; i-- > 0; ) {  
  39.              const SeqChain& seqChain = mSeqChains.itemAt(i);  
  40.              if (seqChain.seq == currentSeq) {  
  41.                  currentSeq = seqChain.chain;  
  42.                  chainSeqs[chainIndex++] = currentSeq;  
  43.                  mSeqChains.removeAt(i);  
  44.              }  
  45.         }  
  46.         status_t status = OK;  
  47.         while (!status && chainIndex-- > 0) {  
  48.             status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);  
  49.         }  
  50.     }  
  51.   
  52.     // Send finished signal for the last message in the batch.  
  53.     return sendUnchainedFinishedSignal(seq, handled);  
  54. }  
  55.   
  56. status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {  
  57.     InputMessage msg;  
  58.     msg.header.type = InputMessage::TYPE_FINISHED;  
  59.     msg.body.finished.seq = seq;  
  60.     msg.body.finished.handled = handled;  
  61.     return mChannel->sendMessage(&msg);  
  62. }  
  63.   
  64. //这个和server端发送事件过来一样的,只不过这次是client发送消息给server  
  65. status_t InputChannel::sendMessage(const InputMessage* msg) {  
  66.     size_t msgLength = msg->size();  
  67.     ssize_t nWrite;  
  68.     do {  
  69.         nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);  
  70.     } while (nWrite == -1 && errno == EINTR);  
  71.     return OK;  
  72. }  


/********************************

* 本文来自博客  “爱踢门”

* 转载请标明出处:http://blog.csdn.net/itleaks

******************************************/

你可能感兴趣的:(Android输入系统之InputChannel(下))