这篇博客我们接上面一篇博客,回答上篇博客中,最后的connection对象是如何来的。
一、InputManagerService的registerInputChannel方法
我们先从InputManagerService的registerInputChannel方法分析:
public void registerInputChannel(InputChannel inputChannel,
InputWindowHandle inputWindowHandle) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
再来看看nativeRegisterInputChannel函数
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
......
sp<InputWindowHandle> inputWindowHandle =
android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
status_t status = im->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);
......
}
最后调用了NativeInputManager的registerInputChannel函数
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
return mInputManager->getDispatcher()->registerInputChannel(
inputChannel, inputWindowHandle, monitor);
}
而这个函数,最终是调用了InputDispatcher的registerInputChannel函数:
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
{ // acquire lock
AutoMutex _l(mLock);
if (getConnectionIndexLocked(inputChannel) >= 0) {
ALOGW("Attempted to register already registered input channel '%s'",
inputChannel->getName().string());
return BAD_VALUE;
}
sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);//新建了一个connection
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);//把connection加入列表中
if (monitor) {
mMonitoringChannels.push(inputChannel);
}
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);//加入epoll检测中
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
return OK;
}
在这个函数中创建了一个Connection对象,并把这个对象加入列表中。如果有多个Connection,那么分发的消息是发给那个Connection呢,前面dispatchKeyLocked函数会调用函数findFocusedWindowTargetsLocked得到当前拥有焦点的窗口的InputChannel信息,然后再调用getConnectionIndexLocked函数得到mConnectionsByFd列表中和InputChannel关联的Connection对象的index。
ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
if (connection->inputChannel.get() == inputChannel.get()) {
return connectionIndex;
}
}
return -1;
}
有了这个index也就得到了conection对象了,现在我们知道了上篇博客最后startDispatchCycleLocked函数中使用的Connection对象其实是和当前有焦点的窗口关联的对象。
下面我们继续分析它的inputPublisher成员的publishKeyEvent函数:
status_t InputPublisher::publishKeyEvent(
......
InputMessage msg;
msg.header.type = InputMessage::TYPE_KEY;
......
return mChannel->sendMessage(&msg);
}
publishKeyEvent函数调用了mChannel的sendMessage函数,这个mChannel是创建Connection对象时的参数InputChannel。
这边的InputChannel是前面nativeRegisterInputChann