一、InputDispatcher的notifyKey函数
接上一篇我们我们分析到InputDispatcher的notifyKey函数:
1. void InputDispatcher::notifyKey(const
2. if
3. return;
4. }
5.
6. uint32_t policyFlags = args->policyFlags;
7. int32_t flags = args->flags;
8. int32_t metaState = args->metaState;
9. if
10. policyFlags |= POLICY_FLAG_VIRTUAL;
11. flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
12. }
13. if
14. metaState |= AMETA_FUNCTION_ON;
15. }
16.
17. policyFlags |= POLICY_FLAG_TRUSTED;
18.
19. int32_t keyCode = args->keyCode;
20. if
21. int32_t newKeyCode = AKEYCODE_UNKNOWN;
22. if
23. newKeyCode = AKEYCODE_BACK;
24. else if
25. newKeyCode = AKEYCODE_HOME;
26. }
27. if
28. AutoMutex _l(mLock);
29. struct
30. mReplacedKeys.add(replacement, newKeyCode);
31. keyCode = newKeyCode;
32. metaState &= ~AMETA_META_ON;
33. }
34. else if
35. // In order to maintain a consistent stream of up and down events, check to see if the key
36. // going up is one we've replaced in a down event and haven't yet replaced in an up event,
37. // even if the modifier was released between the down and the up events.
38. AutoMutex _l(mLock);
39. struct
40. ssize_t index = mReplacedKeys.indexOfKey(replacement);
41. if
42. keyCode = mReplacedKeys.valueAt(index);
43. mReplacedKeys.removeItemsAt(index);
44. metaState &= ~AMETA_META_ON;
45. }
46. }
47.
48. KeyEvent event;
49. event.initialize(args->deviceId, args->source, args->action,
50. flags, keyCode, args->scanCode, metaState, 0,
51. args->downTime, args->eventTime);
52.
53. /*byref*/ policyFlags);//这个函数是调用了java的PhoneWindowManager
54.
55. bool
56. // acquire lock
57. mLock.lock();
58.
59. if
60. mLock.unlock();
61.
62. policyFlags |= POLICY_FLAG_FILTERED;
63. if
64. return; // event was consumed by the filter
65. }
66.
67. mLock.lock();
68. }
69.
70. int32_t repeatCount = 0;
71. new
72. args->deviceId, args->source, policyFlags,
73. args->action, flags, keyCode, args->scanCode,
74. metaState, repeatCount, args->downTime);
75.
76. //将KeyEntry放入到队列中
77. mLock.unlock();
78. // release lock
79.
80. if
81. //唤醒进程
82. }
83. }
我们先来看看mPolicy是构造函数中传进来的,那么我们就要去看InputManager中
1. InputDispatcher::InputDispatcher(const
2. mPolicy(policy),
InputManager的构造函数,还是在InputManager中传入的,那么我们就要跟到NativeInputManager了。
1. InputManager::InputManager(
2. const
3. const
4. const
5. new
6. new
NativeInputManager是把自己传进来了,
1. NativeInputManager::NativeInputManager(jobject contextObj,
2. const
3. true) {
4. JNIEnv* env = jniEnv();
5.
6. mContextObj = env->NewGlobalRef(contextObj);
7. mServiceObj = env->NewGlobalRef(serviceObj);
8.
9. {
10. AutoMutex _l(mLock);
11. mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
12. mLocked.pointerSpeed = 0;
13. true;
14. false;
15. }
16. true;
17.
18. new
19. new InputManager(eventHub, this, this);
因此在InputDispatcher中调用interceptKeyBeforeQueueing,是调用了NativeInputManager的interceptKeyBeforeQueueing函数
1. void NativeInputManager::interceptKeyBeforeQueueing(const
2. uint32_t& policyFlags) {
3. // Policy:
4. // - Ignore untrusted events and pass them along.
5. // - Ask the window manager what to do with normal events and trusted injected events.
6. // - For normal events wake and brighten the screen if currently off or dim.
7. bool
8. if
9. policyFlags |= POLICY_FLAG_INTERACTIVE;
10. }
11. if
12. nsecs_t when = keyEvent->getEventTime();
13. JNIEnv* env = jniEnv();
14. jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
15. jint wmActions;
16. if
17. //反调用PhoneWindowManager
18. gServiceClassInfo.interceptKeyBeforeQueueing,
19. keyEventObj, policyFlags);
20. if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
21. wmActions = 0;
22. }
23. android_view_KeyEvent_recycle(env, keyEventObj);
24. env->DeleteLocalRef(keyEventObj);
25. else
26. "Failed to obtain key event object for interceptKeyBeforeQueueing.");
27. wmActions = 0;
28. }
29.
30. /*byref*/
31. else
32. if
33. policyFlags |= POLICY_FLAG_PASS_TO_USER;
34. }
35. }
36. }
在这个函数中会反调到PhoneWindowManager中的interceptKeyBeforeQueueing函数,在上层的result返回result &= ~ACTION_PASS_TO_USER就不会发送到应用进程了。
返回结果保存在wmActions中,然后调用了handleInterceptActions函数:
1. void
2. uint32_t& policyFlags) {
3. if
4. policyFlags |= POLICY_FLAG_PASS_TO_USER;
5. else
6. }
7. }
如果PhoneWindowManager返回的是result &= ~ACTION_PASS_TO_USER,policyFlags |= POLICY_FLAG_PASS_TO_USER就没有了。
继续分析InputDispatcher::notifyKey函数,调用完interceptKeyBeforeQueueing,然后 新建了一个KeyEntry对象后,调用enqueueInboundEventLocked函数。
1. bool
2. bool
3. //放入队列尾
4. traceInboundQueueLengthLocked();
5.
6. switch
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. static_cast<KeyEntry*>(entry);
12. if
13. if
14. true;
15. else if
16. if
17. #if DEBUG_APP_SWITCH
18. "App switch is pending!");
19. #endif
20. mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
21. false;
22. true;
23. }
24. }
25. }
26. break;
27. }
继续分析InputDispatcher::notifyKey函数,最后会调用mLooper的wake函数唤醒线程,这个我们就不详细分析了。之前分析过。
二、InputDispatcher分发
notifyKey我们分析完了,接下来我们分析之前的InputDispatcherThread,线程不断的循环调用了InputDispatcher的dispatchOnce函数,下面我们来看下:
1. void
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
10. //分发消息
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
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
23. //进入epoll
24. }
继续分析dispatchOnceInnerLocked函数
1. void
2. ........
3.
4. switch (mPendingEvent->type) {//根据类型不同
5. case
6. ConfigurationChangedEntry* typedEntry =
7. static_cast<ConfigurationChangedEntry*>(mPendingEvent);
8. done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
9. // configuration changes are never dropped
10. break;
11. }
12.
13. case
14. DeviceResetEntry* typedEntry =
15. static_cast<DeviceResetEntry*>(mPendingEvent);
16. done = dispatchDeviceResetLocked(currentTime, typedEntry);
17. // device resets are never dropped
18. break;
19. }
20.
21. case
22. static_cast<KeyEntry*>(mPendingEvent);
23. if
24. if
25. true);
26. false;
27. else if
28. dropReason = DROP_REASON_APP_SWITCH;
29. }
30. }
31. if
32. && isStaleEventLocked(currentTime, typedEntry)) {
33. dropReason = DROP_REASON_STALE;
34. }
35. if
36. dropReason = DROP_REASON_BLOCKED;
37. }
38. done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
39. break;
40. }
41.
42. case
43. static_cast<MotionEntry*>(mPendingEvent);
44. if
45. dropReason = DROP_REASON_APP_SWITCH;
46. }
47. if
48. && isStaleEventLocked(currentTime, typedEntry)) {
49. dropReason = DROP_REASON_STALE;
50. }
51. if
52. dropReason = DROP_REASON_BLOCKED;
53. }
54. done = dispatchMotionLocked(currentTime, typedEntry,
55. &dropReason, nextWakeupTime);
56. break;
57. }
58.
59. default:
60. false);
61. break;
62. }
63.
64. if
65. if
66. dropInboundEventLocked(mPendingEvent, dropReason);
67. }
68. mLastDropReason = dropReason;
69.
70. releasePendingEventLocked();
71. // force next poll to wake up immediately
72. }
73. }
这个函数中,最后会根据类型不同调用不同的方法,我们是TYPE_KEY,调用了dispatchKeyLocked方法,一路跟下去有很多函数,我们就直接到最后的函数startDispatchCycleLocked函数:
1. void
2. const
3.
4. while
5. && !connection->outboundQueue.isEmpty()) {
6. DispatchEntry* dispatchEntry = connection->outboundQueue.head;
7. dispatchEntry->deliveryTime = currentTime;
8.
9. // Publish the event.
10. status_t status;
11. EventEntry* eventEntry = dispatchEntry->eventEntry;
12. switch
13. case
14. static_cast<KeyEntry*>(eventEntry);
15.
16. // Publish the key event.
17. status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
18. keyEntry->deviceId, keyEntry->source,
19. dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
20. keyEntry->keyCode, keyEntry->scanCode,
21. keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
22. keyEntry->eventTime);
23. break;
24. }
这个函数会根据Event类型来分别处理,最后调用了connection对象的inputPublisher的publishKeyEvent函数。
下篇博客我们来继续分析下connection这个对象从何而来?