InputReader.pollOnce,EventHub.getEvent这两个函数分别定义在frameworks/base/libs/ui/InputReader.cpp和frameworks/base/libs/ui/EventHub.cpp文件中,前面我们在分析InputManager的启动过程的Step 17和Step 18时,已经看到过这两个函数了。InputReaderThread线程会不断地循环调用InputReader.pollOnce函数来读入键盘事件,而实际的键盘事件读入操作是由EventHub.getEvent函数来进行的。如果当前没有键盘事件发生,InputReaderThread线程就会睡眠在EventHub.getEvent函数上,而当键盘事件发生后,就会把这个事件封装成一个RawEvent对象,然后返回到pollOnce函数中,执行process函数进一步处理:
SETP1:
InputReaderThread线程的处理:
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector
{// acquire lock
AutoMutex _l(mLock);
oldGeneration = mGeneration;
timeoutMillis = -1;
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
}// release lock
size_t count =mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
//最关键的步骤,获取按键事件。前面有分析过。这里就是调用的地方。
{// acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
processEventsLocked(mEventBuffer, count);
//继续处理获取到的mEventBuffer.这里只关注流程,细节判断暂时不跟进。
}
。。。。。。。。。。。
}
SETP2:
frameworks\native\services\inputflinger\InputReader.cpp
void InputReader::processEventsLocked(constRawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type int32_t deviceId = rawEvent->deviceId; while (batchSize < count) { if (rawEvent[batchSize].type>= EventHubInterface::FIRST_SYNTHETIC_EVENT || rawEvent[batchSize].deviceId !=deviceId) { break; } batchSize += 1; } #if DEBUG_RAW_EVENTS ALOGD("BatchSize: %d Count: %d", batchSize, count); #endif processEventsForDeviceLocked(deviceId,rawEvent, batchSize); } else { ……. } count -= batchSize; rawEvent += batchSize; } } Setp3: void InputReader::processEventsForDeviceLocked(int32_tdeviceId, const RawEvent* rawEvents, size_t count) { ssize_t deviceIndex = mDevices.indexOfKey(deviceId); if (deviceIndex < 0) { ALOGW("Discarding event for unknown deviceId %d.", deviceId); return; } InputDevice* device = mDevices.valueAt(deviceIndex); if (device->isIgnored()) { //ALOGD("Discarding event for ignored deviceId %d.",deviceId); return; } device->process(rawEvents, count); //首先从rawEvent中取得触发键盘事件设备对象device,然后调用它的process函数进行处理 } SETP4: void InputDevice::process(constRawEvent* rawEvents, size_t count) { // Process all of the events in order for each mapper. // We cannot simply ask each mapper to process them in bulk becausemappers may // have side-effects that must be interleaved. For example, joystick movement events and // gamepad button presses are handled by different mappers but theyshould be dispatched // in the order received. size_t numMappers = mMappers.size(); for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) { #if DEBUG_RAW_EVENTS ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08xwhen=%lld", rawEvent->deviceId,rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when); #endif if (mDropUntilNextSync) { if (rawEvent->type == EV_SYN && rawEvent->code ==SYN_REPORT) { mDropUntilNextSync = false; #if DEBUG_RAW_EVENTS ALOGD("Recovered from input event bufferoverrun."); #endif } else { #if DEBUG_RAW_EVENTS ALOGD("Dropped input eventwhile waiting for next input sync."); #endif } } else if (rawEvent->type == EV_SYN && rawEvent->code ==SYN_DROPPED) { ALOGI("Detected input event buffer overrun for device %s.",getName().string()); mDropUntilNextSync = true; reset(rawEvent->when); } else { for (size_t i = 0; i < numMappers; i++) { InputMapper* mapper =mMappers[i]; mapper->process(rawEvent); /* 这里的mMapper成员变量保存了一系列输入设备事件处理象,例如负责处理键盘事件的KeyboardKeyMapper对象、负责处理轨迹球事件的TrackballInputMapper对象以及负责处理触摸屏事件的TouchInputMapper对象,它们是在InputReader类的成员函数createDevice中创建的。这里查询每一个InputMapper对象是否要对当前发生的事件进行处理。由于发生的是键盘事件,真正会对该事件进行处理的只有KeyboardKeyMapper对象。 */ } } } } STEP5: frameworks\native\services\inputflinger\InputReader.cpp void KeyboardInputMapper::process(constRawEvent* rawEvent) { switch (rawEvent->type) { case EV_KEY: { int32_t scanCode = rawEvent->code; int32_t usageCode = mCurrentHidUsage; mCurrentHidUsage = 0; if (isKeyboardOrGamepadKey(scanCode)) { int32_t keyCode; uint32_t flags; if (getEventHub()->mapKey(getDeviceId(),scanCode, usageCode, &keyCode, &flags)) // 这里应该是将linux_code的键值,转换为了android_key的键值。很关键的一个转换。后面专门分析如何转换。一般是通过generac.lk文件对应的。带验证。 { keyCode = AKEYCODE_UNKNOWN; flags = 0; } processKey(rawEvent->when, rawEvent->value!= 0, keyCode, scanCode, flags); } break; } 。。。。。。 } STEP6: voidKeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) { 。。。。。。 NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); getListener()->notifyKey(&args); //这个notifyKey 应该是对应InputDispatcher.cpp中的notifykey(),具体如何通讯的,待学习。 ALOGD_READER("notifyKey - eventTime=%lld,deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, " "flags=0x%x, keyCode=0x%x,scanCode=0x%x, metaState=0x%x, downTime=%lld", args.eventTime, args.deviceId,args.source, args.policyFlags, args.action, args.flags,args.keyCode, args.scanCode, args.metaState, args.downTime); } STEP 7: \frameworks\native\services\inputflinger\InputDispatcher.cpp void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { #if DEBUG_INBOUND_EVENT_DETAILS ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x,policyFlags=0x%x, action=0x%x, " "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x,downTime=%lld", args->eventTime, args->deviceId, args->source,args->policyFlags, args->action, args->flags, args->keyCode, args->scanCode, args->metaState, args->downTime); #endif if (!validateKeyEvent(args->action)) { return; } uint32_t policyFlags = args->policyFlags; int32_t flags = args->flags; int32_t metaState = args->metaState; if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags &AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) { policyFlags |= POLICY_FLAG_VIRTUAL; flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY; } if (policyFlags & POLICY_FLAG_FUNCTION) { metaState |= AMETA_FUNCTION_ON; } policyFlags |= POLICY_FLAG_TRUSTED; int32_t keyCode = args->keyCode; if (metaState & AMETA_META_ON && args->action ==AKEY_EVENT_ACTION_DOWN) { int32_t newKeyCode = AKEYCODE_UNKNOWN; if (keyCode == AKEYCODE_DEL) { newKeyCode = AKEYCODE_BACK; } else if (keyCode == AKEYCODE_ENTER) { newKeyCode = AKEYCODE_HOME; } if (newKeyCode != AKEYCODE_UNKNOWN) { AutoMutex _l(mLock); struct KeyReplacement replacement = {keyCode, args->deviceId}; mReplacedKeys.add(replacement, newKeyCode); keyCode = newKeyCode; metaState &= ~AMETA_META_ON; } }else if (args->action == AKEY_EVENT_ACTION_UP) { // In order to maintain a consistent stream of up and down events, checkto see if the key // going up is one we've replaced in a down event and haven't yetreplaced in an up event, // even if the modifier was released between the down and the up events. AutoMutex _l(mLock); struct KeyReplacement replacement = {keyCode, args->deviceId}; ssize_t index = mReplacedKeys.indexOfKey(replacement); if (index >= 0) { keyCode = mReplacedKeys.valueAt(index); mReplacedKeys.removeItemsAt(index); metaState &= ~AMETA_META_ON; } } KeyEvent event; event.initialize(args->deviceId, args->source, args->action, flags, keyCode, args->scanCode, metaState, 0, args->downTime, args->eventTime); mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/policyFlags); /* mPolicy为WindowManagerService注册的时候所申请。对应的为PhoneWindowManager: frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.java 这个interceptKeyBeforeQueueing会拦截一些按键,如POWER,HOME,BACK,VOL+,VOL-等常用的公共按键,所以只要分析这些系统共用的按键,应该就是到这里了。 */ bool needWake; {// acquire lock mLock.lock(); if (shouldSendKeyToInputFilterLocked(args)) { mLock.unlock(); policyFlags |= POLICY_FLAG_FILTERED; if (!mPolicy->filterInputEvent(&event, policyFlags)) { return; // event wasconsumed by the filter } mLock.lock(); } int32_t repeatCount = 0; KeyEntry* newEntry = new KeyEntry(args->eventTime, args->deviceId,args->source, policyFlags, args->action, flags, keyCode,args->scanCode, metaState, repeatCount,args->downTime); needWake = enqueueInboundEventLocked(newEntry); //enqueueInboundEventLocked函数把这个按键事件封装成一个KeyEntry结构加入到//InputDispatcher类的mInboundQueue队列中去:还有就是判断是否要唤醒InputDispatccherThread //线程 mLock.unlock(); }// release lock if (needWake) { mLooper->wake(); //looper在另外学习,这里有按键会唤醒InputDispatccherThread,继续对按键进行处理。 } } 参考说明:M版本应该是有修改,没有找到Looper.cpp文档,再学习吧。 Looper.wake:这个函数定义在frameworks/base/libs/utils/Looper.cpp文件中,在前面一篇文章Android应用程序消息处理机制(Looper、Handler)分析中,我们已经分析过这个函数了,这里不再详述,简单来说,它的作用就是用来唤醒睡眠在Looper对象内部的管道读端的线程,在我们的这个场景中,睡眠在Looper对象内部的管道读端的线程就是InputDispatccherThread线程了。 我们知道,此时InputDispatccherThread线程正在InputDispatcher类的dispatchOnce函数中通过调用mLooper->loopOnce函数进入睡眠状态。当它被唤醒以后,它就会从InputDispatcher类的dispatchOnce函数返回到InputDispatcherThread类的threadLoop函数,而InputDispatcherThread类的threadLoop函数是循环执行的,于是,它又会再次进入到InputDispatcher类的dispatchOnce函数来处理当前发生的键盘事件。 STEP 8: \frameworks\native\services\inputflinger\InputDispatcher.cpp voidInputDispatcher::dispatchOnce() { nsecs_t nextWakeupTime = LONG_LONG_MAX; { // acquire lock AutoMutex _l(mLock); mDispatcherIsAliveCondition.broadcast(); // Run a dispatch loop if there are nopending commands. // The dispatch loop might enqueuecommands to run afterwards. if (!haveCommandsLocked()) { dispatchOnceInnerLocked(&nextWakeupTime); } …… } STEP 9: voidInputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { nsecs_t currentTime = now(); // Reset the key repeat timer whenever normal dispatch is suspendedwhile the // device is in a non-interactive state. This is to ensure that we abort a key // repeat if the device is just coming out of sleep. if (!mDispatchEnabled) { resetKeyRepeatLocked(); } // If dispatching is frozen, do not process timeouts or try to deliverany new events. if (mDispatchFrozen) { #if DEBUG_FOCUS ALOGD("Dispatch frozen. Waiting some more."); #endif return; } // Optimize latency of app switches. // Essentially we start a short timeout when an app switch key (HOME /ENDCALL) has // been pressed. When it expires,we preempt dispatch and drop all other pending events. bool isAppSwitchDue = mAppSwitchDueTime <= currentTime; if (mAppSwitchDueTime < *nextWakeupTime) { *nextWakeupTime = mAppSwitchDueTime; } // Ready to start a new event. // If we don't already have a pending event, go grab one. if (! mPendingEvent) { if (mInboundQueue.isEmpty()) { if (isAppSwitchDue) { // The inbound queue is emptyso the app switch key we were waiting // for will never arrive. Stop waiting for it. resetPendingAppSwitchLocked(false); isAppSwitchDue = false; } // Synthesize a key repeat if appropriate. if (mKeyRepeatState.lastKeyEntry) { if (currentTime >=mKeyRepeatState.nextRepeatTime) { mPendingEvent =synthesizeKeyRepeatLocked(currentTime); } else { if(mKeyRepeatState.nextRepeatTime < *nextWakeupTime) { *nextWakeupTime =mKeyRepeatState.nextRepeatTime; } } } // Nothing to do if there is no pending event. if (!mPendingEvent) { return; } } else { // Inbound queue has at least one entry. mPendingEvent =mInboundQueue.dequeueAtHead(); //获取到之前增加到管道里面的KEY,管道的知识待学习。 traceInboundQueueLengthLocked(); } 。。。。。。 switch (mPendingEvent->type) { …… case EventEntry::TYPE_KEY: { KeyEntry* typedEntry = static_cast if (isAppSwitchDue) { if (isAppSwitchKeyEventLocked(typedEntry)) { resetPendingAppSwitchLocked(true); isAppSwitchDue = false; } else if (dropReason == DROP_REASON_NOT_DROPPED) { dropReason =DROP_REASON_APP_SWITCH; } } if (dropReason == DROP_REASON_NOT_DROPPED &&isStaleEventLocked(currentTime, typedEntry)) { dropReason = DROP_REASON_STALE; } if (dropReason == DROP_REASON_NOT_DROPPED &&mNextUnblockedEvent) { dropReason = DROP_REASON_BLOCKED; } done = dispatchKeyLocked(currentTime,typedEntry, &dropReason, nextWakeupTime); //开始派发KEY。 break; } case EventEntry::TYPE_MOTION: { …… } default: ALOG_ASSERT(false); break; } if (done) { if (dropReason != DROP_REASON_NOT_DROPPED) { dropInboundEventLocked(mPendingEvent, dropReason); } mLastDropReason = dropReason; releasePendingEventLocked(); *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately } } STEP 10: bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry*entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { // Preprocessing. …… // Identify targets. Vector int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime); //检查mFocusedWindowHandle是否能接收输入事件。如果可以,将之以InputTarget的形式加到目//标窗口数组中 if (injectionResult == INPUT_EVENT_INJECTION_PENDING) { return false; } setInjectionResultLocked(entry, injectionResult); if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) { return true; } addMonitoringTargetsLocked(inputTargets); // Dispatch the key. dispatchEventLocked(currentTime, entry, inputTargets); return true; } Step 11: voidInputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry, const Vector #if DEBUG_DISPATCH_CYCLE ALOGD("dispatchEventToCurrentInputTargets"); #endif ALOG_ASSERT(eventEntry->dispatchInProgress); // should already havebeen set to true pokeUserActivityLocked(eventEntry); //待分析,还不太理解什么意思。 /* 这里会封装成CommandEntry插入到mCommandQueue队列中,后面的runCommandLockedInterruptible()函数中会调用doInterceptKeyBeforeDispatchingLockedInterruptible()来让PWM有机会进行处理 */ for (size_t i = 0; i < inputTargets.size(); i++) { const InputTarget& inputTarget = inputTargets.itemAt(i); ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel); if (connectionIndex >= 0) { sp prepareDispatchCycleLocked(currentTime,connection, eventEntry, &inputTarget); } else { #if DEBUG_FOCUS ALOGD("Dropping eventdelivery to target with channel '%s' because it " "is no longerregistered with the input dispatcher.", inputTarget.inputChannel->getName().string()); #endif } } } STEP 12: voidInputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime, const sp …… // Split a motion event if needed. if (inputTarget->flags & InputTarget::FLAG_SPLIT) { ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION); MotionEntry* originalMotionEntry =static_cast if (inputTarget->pointerIds.count() !=originalMotionEntry->pointerCount) { MotionEntry* splitMotionEntry =splitMotionEvent( originalMotionEntry,inputTarget->pointerIds); if (!splitMotionEntry) { return; // split event wasdropped } #if DEBUG_FOCUS ALOGD("channel '%s' ~ Splitmotion event.", connection->getInputChannelName()); logOutboundMotionDetailsLocked(" ", splitMotionEntry); #endif enqueueDispatchEntriesLocked(currentTime,connection, splitMotionEntry,inputTarget); splitMotionEntry->release(); return; } } // Not splitting. Enqueuedispatch entries for the event as is. enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget); } STEP 13: //对dispatchEntry的封装 void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp bool wasEmpty = connection->outboundQueue.isEmpty(); // Enqueue dispatch entries for the requested modes. enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_OUTSIDE); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_IS); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER); // If the outbound queue was previously empty, start the dispatch cyclegoing. if (wasEmpty && !connection->outboundQueue.isEmpty()) { startDispatchCycleLocked(currentTime,connection); } } STEP 14: voidInputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, const sp #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName()); #endif //startDispatchCycleLocked函数会检查相应连接的输出缓冲中(connection->outboundQueue)是否////有事件要发送的,有的话会通过InputChannel发送出去。 while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.isEmpty()) { DispatchEntry* dispatchEntry = connection->outboundQueue.head; dispatchEntry->deliveryTime = currentTime; // Publish the event. status_t status; EventEntry* eventEntry = dispatchEntry->eventEntry; switch (eventEntry->type) { case EventEntry::TYPE_KEY: { KeyEntry* keyEntry = static_cast // Publish the key event. status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq, keyEntry->deviceId,keyEntry->source, dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags, keyEntry->keyCode,keyEntry->scanCode, keyEntry->metaState,keyEntry->repeatCount, keyEntry->downTime, keyEntry->eventTime); break; } case EventEntry::TYPE_MOTION: { …… } ……. // Re-enqueue the event on the wait queue. connection->outboundQueue.dequeue(dispatchEntry); traceOutboundQueueLengthLocked(connection); connection->waitQueue.enqueueAtTail(dispatchEntry); traceWaitQueueLengthLocked(connection); } } Step 15: frameworks\native\libs\input\InputTransport.cpp status_t InputPublisher::publishKeyEvent( uint32_t seq, int32_t deviceId, int32_t source, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime) { #if DEBUG_TRANSPORT_ACTIONS ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u,deviceId=%d, source=0x%x, " "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x,repeatCount=%d," "downTime=%lld, eventTime=%lld", mChannel->getName().string(), seq, deviceId, source, action, flags, keyCode, scanCode, metaState,repeatCount, downTime, eventTime); #endif if (!seq) { ALOGE("Attempted to publish a key event with sequence number0."); return BAD_VALUE; } InputMessage msg; msg.header.type = InputMessage::TYPE_KEY; msg.body.key.seq = seq; msg.body.key.deviceId = deviceId; msg.body.key.source = source; msg.body.key.action = action; msg.body.key.flags = flags; msg.body.key.keyCode = keyCode; msg.body.key.scanCode = scanCode; msg.body.key.metaState = metaState; msg.body.key.repeatCount = repeatCount; msg.body.key.downTime = downTime; msg.body.key.eventTime = eventTime; return mChannel->sendMessage(&msg); } 到这里,inputdispatcher的工作就完成了。通过mchannel将消息发送出去。但是同时问题又来了。Mchannel是谁,消息有事发送给谁呢。这里我理解也是一个客户端服务器机制。这里的客户端为上层的ViewRootImpl的setView中注册。服务器端则是注册到InputDispatcher中。所以这个mChannel->sendMessage(&msg); 其实就是将服务器端的InputDispatcher 注册的inputchannel,发送给其对于的客户端ViewRootImpl。下面我们来具体看看该服务器和客户端的建立和配对过程。 STEP 1: frameworks\base\core\java\android\view\ViewRootImpl.java publicvoid setView(Viewview, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { …… // Schedule the first layout -before- adding to the window // manager, to make sure we do the relayout before receiving // any other events from the system. requestLayout(); if ((mWindowAttributes.inputFeatures &WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { mInputChannel = new InputChannel();//创建客户端的inputchanel } try { mOrigWindowType =mWindowAttributes.type; mAttachInfo.mRecomputeGlobalAttributes = true; collectViewAttributes(); res = mWindowSession.addToDisplay(mWindow, mSeq,mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mOutsets,mInputChannel);//将客户端带入WMS,去创建对应的服务器端。 …… } /* setView方法中如果Window的属性能接受输入,而且还没有创建InputChannel,则会新创建一个InputChannel对象。这个对象会通过mWindowSession的addToDisplay方法传递到WindowManagerService中,最后再会调用WMS的addWindow方法,addWindow有下面这段代码: */ Step 2: frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java public int addWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets, Rect outOutsets, InputChannel outInputChannel) { int[] appOp = new int[1]; int res = mPolicy.checkAddPermission(attrs, appOp); if (res != WindowManagerGlobal.ADD_OKAY) { return res; } …… if (outInputChannel != null &&(attrs.inputFeatures &WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) { /** M: [ALPS00044207] @{ */ try { String name = win.makeInputChannelName(); InputChannel[] inputChannels =InputChannel.openInputChannelPair(name);//创建channelPair win.setInputChannel(inputChannels[0]);//将 channelPair 的inputChannels[0]给到win.mInputChannel,让下面去继续注册。 inputChannels[1].transferTo(outInputChannel);//参数传进来的client端填充到channelPair 的inputChannels[1]中去。 mInputManager.registerInputChannel(win.mInputChannel,win.mInputWindowHandle);//继续去注册 } …… } /* addWIndow方法中先调用了InputChannel的openInputChannelPair来返回一个InputChannel对象的数组channelPair,inputChannels[0]为其创建的server 端,inputChannels[1]则为client端。然后将inputChannel[0]设置到win中去。接着inputChannel[1]转换成和客户端传递过来的outInputChannel对象,最后调用了InputManagerService中的registerInputChannel方法。 */ SETP3: frameworks\base\services\core\java\com\android\server\input\ InputManagerService.java public voidregisterInputChannel(InputChannel inputChannel, InputWindowHandleinputWindowHandle) { if (inputChannel == null) { throw newIllegalArgumentException("inputChannel must not be null."); } nativeRegisterInputChannel(mPtr, inputChannel,inputWindowHandle, false); } STEP4: \frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp static voidnativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */, jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj,jboolean monitor) { NativeInputManager* im =reinterpret_cast sp inputChannelObj); if (inputChannel == NULL) { throwInputChannelNotInitialized(env); return; } sp android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj); status_t status = im->registerInputChannel( env, inputChannel,inputWindowHandle, monitor); if (status) { String8 message; message.appendFormat("Failed to register input channel. status=%d", status); jniThrowRuntimeException(env, message.string()); return; } if (! monitor) { android_view_InputChannel_setDisposeCallback(env, inputChannelObj, handleInputChannelDisposed,im); } } STEP 5: status_tNativeInputManager::registerInputChannel(JNIEnv* /* env */, const sp const sp return mInputManager->getDispatcher()->registerInputChannel( inputChannel, inputWindowHandle,monitor); } STEP 6: frameworks\native\services\inputflinger\ InputDispatcher.cpp status_t InputDispatcher::registerInputChannel(constsp const sp #if DEBUG_REGISTRATION ALOGD("channel '%s' ~ registerInputChannel - monitor=%s",inputChannel->getName().string(), toString(monitor)); #endif { // acquire lock AutoMutex _l(mLock); if (getConnectionIndexLocked(inputChannel) >= 0) { ALOGW("Attempted to registeralready registered input channel '%s'", inputChannel->getName().string()); return BAD_VALUE; } sp int fd = inputChannel->getFd(); mConnectionsByFd.add(fd, connection); if (monitor) { mMonitoringChannels.push(inputChannel); } mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this); } // release lock // Wake the looper because some connections have changed. mLooper->wake(); return OK; } /* 这里的inputChannel 就是publishKeyEvent中的mChannel。但是这个是怎么对应起来的,我现在还没有搞清楚。 所以mChannel->sendMessage(&msg) 实际上就是向ViewRootImpl中的InputChannel客户端发送消息。 到这里,消息就发送到ViewRootImpl里面去了。后面的处理再分析吧。 */