Android应用程序键盘(Keyboard)消息处理机制分析(15)

         Step 7. KeyboardInputMapper.processKey

 

        这个函数定义在frameworks/base/libs/ui/InputReader.cpp文件中:

  1. void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,  
  2.         int32_t scanCode, uint32_t policyFlags) {  
  3.     int32_t newMetaState;  
  4.     nsecs_t downTime;  
  5.     bool metaStateChanged = false;  
  6.   
  7.     { // acquire lock  
  8.      AutoMutex _l(mLock);  
  9.   
  10.      if (down) {  
  11.          // Rotate key codes according to orientation if needed.  
  12.          // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.  
  13.          if (mAssociatedDisplayId >= 0) {  
  14.              int32_t orientation;  
  15.              if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {  
  16.                  return;  
  17.              }  
  18.   
  19.              keyCode = rotateKeyCode(keyCode, orientation);  
  20.          }  
  21.   
  22.          // Add key down.  
  23.          ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  24.          if (keyDownIndex >= 0) {  
  25.              // key repeat, be sure to use same keycode as before in case of rotation  
  26.              keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  27.          } else {  
  28.              // key down  
  29.              if ((policyFlags & POLICY_FLAG_VIRTUAL)  
  30.                  && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {  
  31.                      return;  
  32.              }  
  33.              mLocked.keyDowns.push();  
  34.              KeyDown& keyDown = mLocked.keyDowns.editTop();  
  35.              keyDown.keyCode = keyCode;  
  36.              keyDown.scanCode = scanCode;  
  37.          }  
  38.   
  39.          mLocked.downTime = when;  
  40.      } else {  
  41.          // Remove key down.  
  42.          ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  43.          if (keyDownIndex >= 0) {  
  44.              // key up, be sure to use same keycode as before in case of rotation  
  45.              keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  46.              mLocked.keyDowns.removeAt(size_t(keyDownIndex));  
  47.          } else {  
  48.              // key was not actually down  
  49.              LOGI("Dropping key up from device %s because the key was not down.  "  
  50.                  "keyCode=%d, scanCode=%d",  
  51.                  getDeviceName().string(), keyCode, scanCode);  
  52.              return;  
  53.          }  
  54.      }  
  55.   
  56.      int32_t oldMetaState = mLocked.metaState;  
  57.      newMetaState = updateMetaState(keyCode, down, oldMetaState);  
  58.      if (oldMetaState != newMetaState) {  
  59.          mLocked.metaState = newMetaState;  
  60.          metaStateChanged = true;  
  61.      }  
  62.   
  63.      downTime = mLocked.downTime;  
  64.     } // release lock  
  65.   
  66.   
  67.     if (metaStateChanged) {  
  68.         getContext()->updateGlobalMetaState();  
  69.     }  
  70.   
  71.     getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,  
  72.         down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,  
  73.         AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);  
  74. }  

        这个函数首先对对按键作一些处理,例如,当某一个DPAD键被按下时,根据当时屏幕方向的不同,它所表示的意义也不同,因此,这里需要根据当时屏幕的方向来调整键盘码:

 

  1. // Rotate key codes according to orientation if needed.  
  2. // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.  
  3. if (mAssociatedDisplayId >= 0) {  
  4.     int32_t orientation;  
  5.     if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {  
  6.         return;  
  7.     }  
  8.   
  9.     keyCode = rotateKeyCode(keyCode, orientation);  
  10. }  

        如果这个键是一直按着不放的,不管屏幕的方向如何,必须保证后面的键盘码和前面的一样:

  1. // Add key down.  
  2. ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  3. if (keyDownIndex >= 0) {  
  4.     // key repeat, be sure to use same keycode as before in case of rotation  
  5.     keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  6. else {  
  7.     // key down  
  8.     if ((policyFlags & POLICY_FLAG_VIRTUAL)  
  9.         && mContext->shouldDropVirtualKey(when, getDevice(), keyCode, scanCode)) {  
  10.          return;  
  11.     }  
  12.     mLocked.keyDowns.push();  
  13.     KeyDown& keyDown = mLocked.keyDowns.editTop();  
  14.     keyDown.keyCode = keyCode;  
  15.     keyDown.scanCode = scanCode;  
  16. }  

       如果是第一次按下某个键,还必须把它保存在mLocked.keyDowns里面,就是为了处理上面讲的当这个键盘一直按着不放的时候屏幕方向发生改变的情况。
       如果是松开键盘上的某个键,就把它从mLocked.keyDowns里面删除:

  1. // Remove key down.  
  2. ssize_t keyDownIndex = findKeyDownLocked(scanCode);  
  3. if (keyDownIndex >= 0) {  
  4.     // key up, be sure to use same keycode as before in case of rotation  
  5.     keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;  
  6.     mLocked.keyDowns.removeAt(size_t(keyDownIndex));  
  7. else {  
  8.     // key was not actually down  
  9.     LOGI("Dropping key up from device %s because the key was not down.  "  
  10.         "keyCode=%d, scanCode=%d",  
  11.         getDeviceName().string(), keyCode, scanCode);  
  12.     return;  
  13. }  

        当然,对键盘事件的这些处理不是本文的重点,本文的重点是分析从键盘事件到当前激活的Activity窗口接收到这个键盘消息的过程。

 

        最后,KeyboardInputMappger函数通知InputDispatcher,有键盘事件发生了:

  1. getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,  
  2.     down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,  
  3.     AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);  

你可能感兴趣的:(android,keyboard,消息处理机制分析)