android input 按键分发(inputManager)

来源:互联网 发布:日本直播软件 编辑:程序博客网 时间:2024/05/16 17:01

文章出处:http://blog.csdn.net/shift_wwx/article/details/49764595

请转载的朋友标明出处~~


之前InputManager 的启动过程 已经对inputManager 的启动过程做了简单的介绍。这里先小结一下:

1、InputManagerService 构造,确认DisplayThread,做nativeInit

2、nativeInit ,创建一些实例,例如NativeInputManager、InputManager、EventHub

3、构造InputManager,实例 InputReader、InputDispatcher,并实例 InputReaderThread 对按键进行监控、InputDispatcherThread 对按键进行分发。

对于监控,是根据EventHub来的,这里说一下分发

InputReaderThread线程会不断地循环调用InputReader.loopOnce函数来读入键盘事件,而实际的键盘事件读入操作是由EventHub.getEvent函数来进行的。如果当前没有键盘事件发生,InputReaderThread线程就会睡眠在EventHub.getEvent函数上,而当键盘事件发生后,就会把这个事件封装成一个RawEvent对象,然后返回到loopOnce函数中,执行process函数进一步处理:

[java] view plain copy
  1. processEventsLocked(mEventBuffer, count);  
[java] view plain copy
  1. processEventsForDeviceLocked(deviceId, rawEvent, batchSize);  
[java] view plain copy
  1. void InputReader::processEventsForDeviceLocked(int32_t deviceId,  
  2.         const RawEvent* rawEvents, size_t count) {  
  3.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  
  4.     if (deviceIndex < 0) {  
  5.         ALOGW("Discarding event for unknown deviceId %d.", deviceId);  
  6.         return;  
  7.     }  
  8.   
  9.     InputDevice* device = mDevices.valueAt(deviceIndex);  
  10.     if (device->isIgnored()) {  
  11.         //ALOGD("Discarding event for ignored deviceId %d.", deviceId);  
  12.         return;  
  13.     }  
  14.   
  15.     device->process(rawEvents, count);  
  16. }  
[java] view plain copy
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) {  
  2.     // Process all of the events in order for each mapper.  
  3.     // We cannot simply ask each mapper to process them in bulk because mappers may  
  4.     // have side-effects that must be interleaved.  For example, joystick movement events and  
  5.     // gamepad button presses are handled by different mappers but they should be dispatched  
  6.     // in the order received.  
  7.     size_t numMappers = mMappers.size();  
  8.     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {  
  9. #if DEBUG_RAW_EVENTS  
  10.         ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",  
  11.                 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,  
  12.                 rawEvent->when);  
  13. #endif  
  14.   
  15.         if (mDropUntilNextSync) {  
  16.             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  17.                 mDropUntilNextSync = false;  
  18. #if DEBUG_RAW_EVENTS  
  19.                 ALOGD("Recovered from input event buffer overrun.");  
  20. #endif  
  21.             } else {  
  22. #if DEBUG_RAW_EVENTS  
  23.                 ALOGD("Dropped input event while waiting for next input sync.");  
  24. #endif  
  25.             }  
  26.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {  
  27.             ALOGI("Detected input event buffer overrun for device %s.", getName().string());  
  28.             mDropUntilNextSync = true;  
  29.             reset(rawEvent->when);  
  30.         } else {  
  31.             for (size_t i = 0; i < numMappers; i++) {  
  32.                 InputMapper* mapper = mMappers[i];  
  33.                 mapper->process(rawEvent);  
  34.             }  
  35.         }  
  36.     }  
  37. }  
这里的mMapper成员变量保存了一系列输入设备事件处理象,例如负责处理键盘事件的KeyboardKeyMapper对象、负责处理轨迹球事件的TrackballInputMapper对象以及负责处理触摸屏事件的TouchInputMapper对象, 它们是在InputReader类的成员函数createDevice中创建的。这里查询每一个InputMapper对象是否要对当前发生的事件进行处理。由于发生的是键盘事件,真正会对该事件进行处理的只有KeyboardKeyMapper对象。
[java] view plain copy
  1. void KeyboardInputMapper::process(const RawEvent* rawEvent) {  
  2.     switch (rawEvent->type) {  
  3.     case EV_KEY: {  
  4.         int32_t scanCode = rawEvent->code;  
  5.         int32_t usageCode = mCurrentHidUsage;  
  6.         mCurrentHidUsage = 0;  
  7.   
  8.         if (isKeyboardOrGamepadKey(scanCode)) {  
  9.             int32_t keyCode;  
  10.             uint32_t flags;  
  11.             if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {  
  12.                 keyCode = AKEYCODE_UNKNOWN;  
  13.                 flags = 0;  
  14.             }  
  15.             processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);  
  16.         }  
  17.         break;  
  18.     }  
  19.     case EV_MSC: {  
  20.         if (rawEvent->code == MSC_SCAN) {  
  21.             mCurrentHidUsage = rawEvent->value;  
  22.         }  
  23.         break;  
  24.     }  
  25.     case EV_SYN: {  
  26.         if (rawEvent->code == SYN_REPORT) {  
  27.             mCurrentHidUsage = 0;  
  28.         }  
  29.     }  
  30.     }  
  31. }  
[java] view plain copy
  1. void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,  
  2.         int32_t scanCode, uint32_t policyFlags) {  
  3.   
  4.     if (down) {  
  5.         // Rotate key codes according to orientation if needed.  
  6.         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {  
  7.             keyCode = rotateKeyCode(keyCode, mOrientation);  
  8.         }  
  9.   
  10.         // Add key down.  
  11.         ssize_t keyDownIndex = findKeyDown(scanCode);  
  12.         if (keyDownIndex >= 0) {  
  13.             // key repeat, be sure to use same keycode as before in case of rotation  
  14.             keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;  
  15.         } else {  
  16.             // key down  
  17.             if ((policyFlags & POLICY_FLAG_VIRTUAL)  
  18.                     && mContext->shouldDropVirtualKey(when,  
  19.                             getDevice(), keyCode, scanCode)) {  
  20.                 return;  
  21.             }  
  22.   
  23.             mKeyDowns.push();  
  24.             KeyDown& keyDown = mKeyDowns.editTop();  
  25.             keyDown.keyCode = keyCode;  
  26.             keyDown.scanCode = scanCode;  
  27.         }  
  28.   
  29.         mDownTime = when;  
  30.     } else {  
  31.         // Remove key down.  
  32.         ssize_t keyDownIndex = findKeyDown(scanCode);  
  33.         if (keyDownIndex >= 0) {  
  34.             // key up, be sure to use same keycode as before in case of rotation  
  35.             keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;  
  36.             mKeyDowns.removeAt(size_t(keyDownIndex));  
  37.         } else {  
  38.             // key was not actually down  
  39.             ALOGI("Dropping key up from device %s because the key was not down.  "  
  40.                     "keyCode=%d, scanCode=%d",  
  41.                     getDeviceName().string(), keyCode, scanCode);  
  42.             return;  
  43.         }  
  44.     }  
  45.   
  46.     int32_t oldMetaState = mMetaState;  
  47.     int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);  
  48.     bool metaStateChanged = oldMetaState != newMetaState;  
  49.     if (metaStateChanged) {  
  50.         mMetaState = newMetaState;  
  51.         updateLedState(false);  
  52.     }  
  53.   
  54.     nsecs_t downTime = mDownTime;  
  55.   
  56.     if (metaStateChanged) {  
  57.         getContext()->updateGlobalMetaState();  
  58.     }  
  59.   
  60.     if (down && !isMetaKey(keyCode)) {  
  61.         getContext()->fadePointer();  
  62.     }  
  63.   
  64.     NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,  
  65.             down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,  
  66.             AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);  
  67.     getListener()->notifyKey(&args);  
  68. }  
这个函数首先对按键作一些处理,例如,当某一个DPAD键被按下时,根据当时屏幕方向的不同,它所表示的意义也不同,因此,这里需要根据当时屏幕的方向来调整键盘码:
[java] view plain copy
  1. if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {  
  2.     keyCode = rotateKeyCode(keyCode, mOrientation);  
  3. }  
 如果这个键是一直按着不放的,不管屏幕的方向如何,必须保证后面的键盘码和前面的一样:
[java] view plain copy
  1. ssize_t keyDownIndex = findKeyDown(scanCode);  
 如果是第一次按下某个键,还必须把它保存在mLocked.keyDowns里面,就是为了处理上面讲的当这个键盘一直按着不放的时候屏幕方向发生改变的情况。
如果是松开键盘上的某个键,就把它从mLocked.keyDowns里面删除:
[java] view plain copy
  1. ssize_t keyDownIndex = findKeyDown(scanCode);  
  2. if (keyDownIndex >= 0) {  
  3.     // key up, be sure to use same keycode as before in case of rotation  
  4.     keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;  
  5.     mKeyDowns.removeAt(size_t(keyDownIndex));  
  6. else {  
  7.     // key was not actually down  
  8.     ALOGI("Dropping key up from device %s because the key was not down.  "  
  9.             "keyCode=%d, scanCode=%d",  
  10.             getDeviceName().string(), keyCode, scanCode);  
  11.     return;  
  12. }  

最后是调用notifyKey:

[java] view plain copy
  1. getListener()->notifyKey(&args);  
---->
[java] view plain copy
  1. InputListenerInterface* InputReader::ContextImpl::getListener() {  
  2.     return mReader->mQueuedListener.get();  
  3. }  
---->
[cpp] view plain copy
  1. void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {  
  2.     mArgsQueue.push(new NotifyKeyArgs(*args));  
  3. }  


到这里,我们返回 loopOnce:

[cpp] view plain copy
  1. // Send out a message that the describes the changed input devices.  
  2. if (inputDevicesChanged) {  
  3.     mPolicy->notifyInputDevicesChanged(inputDevices);  
  4. }  
  5.   
  6. // Flush queued events out to the listener.  
  7. // This must happen outside of the lock because the listener could potentially call  
  8. // back into the InputReader's methods, such as getScanCodeState, or become blocked  
  9. // on another thread similarly waiting to acquire the InputReader lock thereby  
  10. // resulting in a deadlock.  This situation is actually quite plausible because the  
  11. // listener is actually the input dispatcher, which calls into the window manager,  
  12. // which occasionally calls into the input reader.  
  13. mQueuedListener->flush();  
如果input device 发生改变的话,会通过notigyInputDevicesChanged 通知上层。

最后会通过mQueuedListener 的flush 激活 InputDispatcher。

通过之前code 看到,processEventsLocked 会将获取的event 以NotifyKeyArgs 的形式存放起来,这里怎么会激活 InputDispatcher呢?

看一下 InputManager 的构造函数:

[java] view plain copy
  1. InputManager::InputManager(  
  2.         const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
  4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
  5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
  6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
  7.     initialize();  
  8. }  
mReader 的第三个参数就是mDispatcher,再来看看InputReader 的构造:

[java] view plain copy
  1. InputReader::InputReader(const sp<EventHubInterface>& eventHub,  
  2.         const sp<InputReaderPolicyInterface>& policy,  
  3.         const sp<InputListenerInterface>& listener) :  
  4.         mContext(this), mEventHub(eventHub), mPolicy(policy),  
  5.         mGlobalMetaState(0), mGeneration(1),  
  6.         mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),  
  7.         mConfigurationChangesToRefresh(0) {  
  8.     mQueuedListener = new QueuedInputListener(listener);  
  9.   
  10.     { // acquire lock  
  11.         AutoMutex _l(mLock);  
  12.   
  13.         refreshConfigurationLocked(0);  
  14.         updateGlobalMetaStateLocked();  
  15.     } // release lock  
  16. }  
第三个参数传进来是 mDispatcher,到这里就变成了mQueuedListener。
所以上面的flush 其实调用的就是 InputDispatcher 的 notifyKey:

[java] view plain copy
  1. void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {  
  2. #if DEBUG_INBOUND_EVENT_DETAILS  
  3.     ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "  
  4.             "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",  
  5.             args->eventTime, args->deviceId, args->source, args->policyFlags,  
  6.             args->action, args->flags, args->keyCode, args->scanCode,  
  7.             args->metaState, args->downTime);  
  8. #endif  
  9.     if (!validateKeyEvent(args->action)) {  
  10.         return;  
  11.     }  
  12.   
  13.     uint32_t policyFlags = args->policyFlags;  
  14.     int32_t flags = args->flags;  
  15.     int32_t metaState = args->metaState;  
  16.     if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {  
  17.         policyFlags |= POLICY_FLAG_VIRTUAL;  
  18.         flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;  
  19.     }  
  20.     if (policyFlags & POLICY_FLAG_FUNCTION) {  
  21.         metaState |= AMETA_FUNCTION_ON;  
  22.     }  
  23.   
  24.     policyFlags |= POLICY_FLAG_TRUSTED;  
  25.   
  26.     int32_t keyCode = args->keyCode;  
  27.     if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {  
  28.         int32_t newKeyCode = AKEYCODE_UNKNOWN;  
  29.         if (keyCode == AKEYCODE_DEL) {  
  30.             newKeyCode = AKEYCODE_BACK;  
  31.         } else if (keyCode == AKEYCODE_ENTER) {  
  32.             newKeyCode = AKEYCODE_HOME;  
  33.         }  
  34.         if (newKeyCode != AKEYCODE_UNKNOWN) {  
  35.             AutoMutex _l(mLock);  
  36.             struct KeyReplacement replacement = {keyCode, args->deviceId};  
  37.             mReplacedKeys.add(replacement, newKeyCode);  
  38.             keyCode = newKeyCode;  
  39.             metaState &= ~AMETA_META_ON;  
  40.         }  
  41.     } else if (args->action == AKEY_EVENT_ACTION_UP) {  
  42.         // In order to maintain a consistent stream of up and down events, check to see if the key  
  43.         // going up is one we've replaced in a down event and haven't yet replaced in an up event,  
  44.         // even if the modifier was released between the down and the up events.  
  45.         AutoMutex _l(mLock);  
  46.         struct KeyReplacement replacement = {keyCode, args->deviceId};  
  47.         ssize_t index = mReplacedKeys.indexOfKey(replacement);  
  48.         if (index >= 0) {  
  49.             keyCode = mReplacedKeys.valueAt(index);  
  50.             mReplacedKeys.removeItemsAt(index);  
  51.             metaState &= ~AMETA_META_ON;  
  52.         }  
  53.     }  
  54.   
  55.     KeyEvent event;  
  56.     event.initialize(args->deviceId, args->source, args->action,  
  57.             flags, keyCode, args->scanCode, metaState, 0,  
  58.             args->downTime, args->eventTime);  
  59.   
  60.     mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);  
  61.   
  62.     bool needWake;  
  63.     { // acquire lock  
  64.         mLock.lock();  
  65.   
  66.         if (shouldSendKeyToInputFilterLocked(args)) {  
  67.             mLock.unlock();  
  68.   
  69.             policyFlags |= POLICY_FLAG_FILTERED;  
  70.             if (!mPolicy->filterInputEvent(&event, policyFlags)) {  
  71.                 return// event was consumed by the filter  
  72.             }  
  73.   
  74.             mLock.lock();  
  75.         }  
  76.   
  77.         int32_t repeatCount = 0;  
  78.         KeyEntry* newEntry = new KeyEntry(args->eventTime,  
  79.                 args->deviceId, args->source, policyFlags,  
  80.                 args->action, flags, keyCode, args->scanCode,  
  81.                 metaState, repeatCount, args->downTime);  
  82.   
  83.         needWake = enqueueInboundEventLocked(newEntry);  
  84.         mLock.unlock();  
  85.     } // release lock  
  86.   
  87.     if (needWake) {  
  88.         mLooper->wake();  
  89.     }  
  90. }  

 函数首先是调用validateKeyEvent函数来验证action参数是否正确:

[java] view plain copy
  1. if (!validateKeyEvent(args->action)) {  
  2.     return;  
  3. }  
[java] view plain copy
  1. static bool isValidKeyAction(int32_t action) {  
  2.     switch (action) {  
  3.     case AKEY_EVENT_ACTION_DOWN:  
  4.     case AKEY_EVENT_ACTION_UP:  
  5.         return true;  
  6.     default:  
  7.         return false;  
  8.     }  
  9. }  
正确的action参数的值只能为AKEY_EVENT_ACTION_DOWN(按下)或者AKEY_EVENT_ACTION_UP(松开)。

接着是在进queue 之前做一些必须要的操作:

[java] view plain copy
  1. KeyEvent event;  
  2. event.initialize(args->deviceId, args->source, args->action,  
  3.         flags, keyCode, args->scanCode, metaState, 0,  
  4.         args->downTime, args->eventTime);  
  5.   
  6. mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags)  
这个会通过jni 回调到InputManagerService.java 中的接口,也就是InputManager 的启动过程中提到的WindowManagerCallbacks。
最后调用enqueueInboundEventLocked函数把这个按键事件封装成一个KeyEntry结构加入到InputDispatcher类的mInboundQueue队列中去:

[java] view plain copy
  1. int32_t repeatCount = 0;  
  2. KeyEntry* newEntry = new KeyEntry(args->eventTime,  
  3.         args->deviceId, args->source, policyFlags,  
  4.         args->action, flags, keyCode, args->scanCode,  
  5.         metaState, repeatCount, args->downTime);  
  6.   
  7. needWake = enqueueInboundEventLocked(newEntry);  
[java] view plain copy
  1. bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {  
  2.     bool needWake = mInboundQueue.isEmpty();  
  3.     mInboundQueue.enqueueAtTail(entry);  
  4.     traceInboundQueueLengthLocked();  
  5.   
  6.     switch (entry->type) {  
  7.     case EventEntry::TYPE_KEY: {  
  8.         // Optimize app switch latency.  
  9.         // If the application takes too long to catch up then we drop all events preceding  
  10.         // the app switch key.  
  11.         KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);  
  12.         if (isAppSwitchKeyEventLocked(keyEntry)) {  
  13.             if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {  
  14.                 mAppSwitchSawKeyDown = true;  
  15.             } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {  
  16.                 if (mAppSwitchSawKeyDown) {  
  17. #if DEBUG_APP_SWITCH  
  18.                     ALOGD("App switch is pending!");  
  19. #endif  
  20.                     mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;  
  21.                     mAppSwitchSawKeyDown = false;  
  22.                     needWake = true;  
  23.                 }  
  24.             }  
  25.         }  
  26.         break;  
  27.     }  
  28.   
  29.     case EventEntry::TYPE_MOTION: {  
  30.         // Optimize case where the current application is unresponsive and the user  
  31.         // decides to touch a window in a different application.  
  32.         // If the application takes too long to catch up then we drop all events preceding  
  33.         // the touch into the other window.  
  34.         MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);  
  35.         if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN  
  36.                 && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)  
  37.                 && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY  
  38.                 && mInputTargetWaitApplicationHandle != NULL) {  
  39.             int32_t displayId = motionEntry->displayId;  
  40.             int32_t x = int32_t(motionEntry->pointerCoords[0].  
  41.                     getAxisValue(AMOTION_EVENT_AXIS_X));  
  42.             int32_t y = int32_t(motionEntry->pointerCoords[0].  
  43.                     getAxisValue(AMOTION_EVENT_AXIS_Y));  
  44.             sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);  
  45.             if (touchedWindowHandle != NULL  
  46.                     && touchedWindowHandle->inputApplicationHandle  
  47.                             != mInputTargetWaitApplicationHandle) {  
  48.                 // User touched a different application than the one we are waiting on.  
  49.                 // Flag the event, and start pruning the input queue.  
  50.                 mNextUnblockedEvent = motionEntry;  
  51.                 needWake = true;  
  52.             }  
  53.         }  
  54.         break;  
  55.     }  
  56.     }  
  57.   
  58.     return needWake;  
  59. }  
从这个函数我们可以看出,在两种情况下,它的返回值为true,一是当加入该键盘事件到mInboundQueue之前,mInboundQueue为空,这表示InputDispatcherThread线程正在睡眠等待InputReaderThread线程的唤醒,因此,它返回true表示要唤醒InputDispatccherThread线程;二是加入该键盘事件到mInboundQueue之前,mInboundQueue不为空,但是此时用户按下的是Home键,按下Home键表示要切换App,我们知道,在切换App时,新的App会把它的键盘消息接收通道注册到InputDispatcher中去,并且会等待InputReader的唤醒,因此,在这种情况下,也需要返回true,表示要唤醒InputDispatccherThread线程。如果不是这两种情况,那么就说明InputDispatccherThread线程现在正在处理前面的键盘事件,不需要唤醒它。
回到前面的notifyKey函数中,根据enqueueInboundEventLocked函数的返回值来决定是否要唤醒InputDispatccherThread线程:
[java] view plain copy
  1. if (needWake) {  
  2.     mLooper->wake();  
  3. }  
 这里,假设needWake为true,于是,就会调用mLooper对象的wake函数来唤醒InputDispatccherThread线程了。

InputManager 的启动过程中说到过 InputReaderThread 和 InputDispatcherThread,在InputDispatccherThread 被唤醒的时候,会调用:

[java] view plain copy
  1. bool InputDispatcherThread::threadLoop() {  
  2.     mDispatcher->dispatchOnce();  
  3.     return true;  
  4. }  
[java] view plain copy
  1. void InputDispatcher::dispatchOnce() {  
  2.     nsecs_t nextWakeupTime = LONG_LONG_MAX;  
  3.     { // acquire lock  
  4.         AutoMutex _l(mLock);  
  5.         mDispatcherIsAliveCondition.broadcast();  
  6.   
  7.         // Run a dispatch loop if there are no pending commands.  
  8.         // The dispatch loop might enqueue commands to run afterwards.  
  9.         if (!haveCommandsLocked()) {  
  10.             dispatchOnceInnerLocked(&nextWakeupTime);  
  11.         }  
  12.   
  13.         // Run all pending commands if there are any.  
  14.         // If any commands were run then force the next poll to wake up immediately.  
  15.         if (runCommandsLockedInterruptible()) {  
  16.             nextWakeupTime = LONG_LONG_MIN;  
  17.         }  
  18.     } // release lock  
  19.   
  20.     // Wait for callback or timeout or wake.  (make sure we round up, not down)  
  21.     nsecs_t currentTime = now();  
  22.     int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);  
  23.     mLooper->pollOnce(timeoutMillis);  
  24. }  
它调用dispatchOnceInnerLocked函数来进一步处理这个键盘事件。
[java] view plain copy
  1. void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {  
  2.     nsecs_t currentTime = now();  
  3.   
  4.     // Reset the key repeat timer whenever normal dispatch is suspended while the  
  5.     // device is in a non-interactive state.  This is to ensure that we abort a key  
  6.     // repeat if the device is just coming out of sleep.  
  7.     if (!mDispatchEnabled) {  
  8.         resetKeyRepeatLocked();  
  9.     }  
  10.   
  11.     // If dispatching is frozen, do not process timeouts or try to deliver any new events.  
  12.     if (mDispatchFrozen) {  
  13. #if DEBUG_FOCUS  
  14.         ALOGD("Dispatch frozen.  Waiting some more.");  
  15. #endif  
  16.         return;  
  17.     }  
  18.   
  19.     // Optimize latency of app switches.  
  20.     // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has  
  21.     // been pressed.  When it expires, we preempt dispatch and drop all other pending events.  
  22.     bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;  
  23.     if (mAppSwitchDueTime < *nextWakeupTime) {  
  24.         *nextWakeupTime = mAppSwitchDueTime;  
  25.     }  
  26.   
  27.     // Ready to start a new event.  
  28.     // If we don't already have a pending event, go grab one.  
  29.     if (! mPendingEvent) {  
  30.         if (mInboundQueue.isEmpty()) {  
  31.             if (isAppSwitchDue) {  
  32.                 // The inbound queue is empty so the app switch key we were waiting  
  33.                 // for will never arrive.  Stop waiting for it.  
  34.                 resetPendingAppSwitchLocked(false);  
  35.                 isAppSwitchDue = false;  
  36.             }  
  37.   
  38.             // Synthesize a key repeat if appropriate.  
  39.             if (mKeyRepeatState.lastKeyEntry) {  
  40.                 if (currentTime >= mKeyRepeatState.nextRepeatTime) {  
  41.                     mPendingEvent = synthesizeKeyRepeatLocked(currentTime);  
  42.                 } else {  
  43.                     if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {  
  44.                         *nextWakeupTime = mKeyRepeatState.nextRepeatTime;  
  45.                     }  
  46.                 }  
  47.             }  
  48.   
  49.             // Nothing to do if there is no pending event.  
  50.             if (!mPendingEvent) {  
  51.                 return;  
  52.             }  
  53.         } else {  
  54.             // Inbound queue has at least one entry.  
  55.             mPendingEvent = mInboundQueue.dequeueAtHead();  
  56.             traceInboundQueueLengthLocked();  
  57.         }  
  58.   
  59.         // Poke user activity for this event.  
  60.         if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {  
  61.             pokeUserActivityLocked(mPendingEvent);  
  62.         }  
  63.   
  64.         // Get ready to dispatch the event.  
  65.         resetANRTimeoutsLocked();  
  66.     }  
  67.   
  68.     // Now we have an event to dispatch.  
  69.     // All events are eventually dequeued and processed this way, even if we intend to drop them.  
  70.     ALOG_ASSERT(mPendingEvent != NULL);  
  71.     bool done = false;  
  72.     DropReason dropReason = DROP_REASON_NOT_DROPPED;  
  73.     if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {  
  74.         dropReason = DROP_REASON_POLICY;  
  75.     } else if (!mDispatchEnabled) {  
  76.         dropReason = DROP_REASON_DISABLED;  
  77.     }  
  78.   
  79.     if (mNextUnblockedEvent == mPendingEvent) {  
  80.         mNextUnblockedEvent = NULL;  
  81.     }  
  82.   
  83.     switch (mPendingEvent->type) {  
  84.     case EventEntry::TYPE_CONFIGURATION_CHANGED: {  
  85.         ConfigurationChangedEntry* typedEntry =  
  86.                 static_cast<ConfigurationChangedEntry*>(mPendingEvent);  
  87.         done = dispatchConfigurationChangedLocked(currentTime, typedEntry);  
  88.         dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped  
  89.         break;  
  90.     }  
  91.   
  92.     case EventEntry::TYPE_DEVICE_RESET: {  
  93.         DeviceResetEntry* typedEntry =  
  94.                 static_cast<DeviceResetEntry*>(mPendingEvent);  
  95.         done = dispatchDeviceResetLocked(currentTime, typedEntry);  
  96.         dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped  
  97.         break;  
  98.     }  
  99.   
  100.     case EventEntry::TYPE_KEY: {  
  101.         KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);  
  102.         if (isAppSwitchDue) {  
  103.             if (isAppSwitchKeyEventLocked(typedEntry)) {  
  104.                 resetPendingAppSwitchLocked(true);  
  105.                 isAppSwitchDue = false;  
  106.             } else if (dropReason == DROP_REASON_NOT_DROPPED) {  
  107.                 dropReason = DROP_REASON_APP_SWITCH;  
  108.             }  
  109.         }  
  110.         if (dropReason == DROP_REASON_NOT_DROPPED  
  111.                 && isStaleEventLocked(currentTime, typedEntry)) {  
  112.             dropReason = DROP_REASON_STALE;  
  113.         }  
  114.         if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {  
  115.             dropReason = DROP_REASON_BLOCKED;  
  116.         }  
  117.         done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);  
  118.         break;  
  119.     }  
  120.   
  121.     case EventEntry::TYPE_MOTION: {  
  122.         MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);  
  123.         if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {  
  124.             dropReason = DROP_REASON_APP_SWITCH;  
  125.         }  
  126.         if (dropReason == DROP_REASON_NOT_DROPPED  
  127.                 && isStaleEventLocked(currentTime, typedEntry)) {  
  128.             dropReason = DROP_REASON_STALE;  
  129.         }  
  130.         if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {  
  131.             dropReason = DROP_REASON_BLOCKED;  
  132.         }  
  133.         done = dispatchMotionLocked(currentTime, typedEntry,  
  134.                 &dropReason, nextWakeupTime);  
  135.         break;  
  136.     }  
  137.   
  138.     default:  
  139.         ALOG_ASSERT(false);  
  140.         break;  
  141.     }  
  142.   
  143.     if (done) {  
  144.         if (dropReason != DROP_REASON_NOT_DROPPED) {  
  145.             dropInboundEventLocked(mPendingEvent, dropReason);  
  146.         }  
  147.   
  148.         releasePendingEventLocked();  
  149.         *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately  
  150.     }  
  151. }  
逻辑忽略先,最后会调用:

[java] view plain copy
  1. done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);  
[java] view plain copy
  1. bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,  
  2.         DropReason* dropReason, nsecs_t* nextWakeupTime) {  
  3.     ......  
  4.       
  5.     // Identify targets.  
  6.     Vector<InputTarget> inputTargets;  
  7.     int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,  
  8.             entry, inputTargets, nextWakeupTime);  
  9.     if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {  
  10.         return false;  
  11.     }  
  12.   
  13.     setInjectionResultLocked(entry, injectionResult);  
  14.     if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {  
  15.         return true;  
  16.     }  
  17.   
  18.     addMonitoringTargetsLocked(inputTargets);  
  19.   
  20.     // Dispatch the key.  
  21.     dispatchEventLocked(currentTime, entry, inputTargets);  
  22.     return true;  
  23. }  
阅读全文
0 0
原创粉丝点击