android input 按鍵分發(inputManager)

文章出處: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. }  
發佈了53 篇原創文章 · 獲贊 17 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章