已经分析了输入事件的读取,处理,分发。我们知道事件的传递是以window为单位传递的,即server只负责将事件传递给某一个或者多个window,window然后再将事件传递给某一个具体的view。一个activity或者dialog对应一个window,但是事件只传递给合适的window,比如对于按键事件,就必须是获得焦点的window,也就是说只能传递给一个window,通常是最上面的程序。找到了合适的window,然后就是将事件添加到window的Connection的事件队列上。其实,到这为止输入事件还只是在server端,即system_server这个进程里,要想让程序获取到事件,肯定必须将事件信息传递到程序端的进程里。这个就是Connection的实现问题了,这个connection的真正逻辑是InputChannel, InputChannel其实就是Linux unix socket的一种封装, unixsocket是linux的一种跨进程通信方式。系统创建InputChannel对即unix socket对,系统server端和程序client各只有其中一个,这样通过unix socket就可以给对方发送消息,而这里的事件就是通过这种方式从系统进程传递到程序进程的。
Server端 InputChannel的创建,首先在window创建一个ViewRootImpl,然后调用ViewRootImpl.java中setView函数
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
mInputChannel = new InputChannel();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(),mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel, Looper.myLooper());
}
创建一个InputChannel,并没有初始化。然后传给mWindowSession.addToDisplay函数。addToDisplay函数最终调用了WindowManagerService.java中addWindow函数
public int addWindow(Session session, IWindow client, int seq,WindowManager.LayoutParams attrs, int viewVisibility, int displayId,Rect outContentInsets, Rect outStableInsets, InputChannel outInputChannel) {
win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
String name = win.makeInputChannelName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
win.setInputChannel(inputChannels[0]);
inputChannels[1].transferTo(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
}
在ViewRootImpl中创建一个WindowState,用于存放InputChannel,便于以后调用InputChannel与InputDispatcher线程的InputChannel通信。
接下来InputChannel.openInputChannelPair函数:
public static InputChannel[] openInputChannelPair(String name) {
return nativeOpenInputChannelPair(name);
}
调用 (JNI)android_view_InputChannel.cpp中android_view_InputChannel_nativeOpenInputChannelPair函数
static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
jclass clazz, jstring nameObj) {
const char* nameChars = env->GetStringUTFChars(nameObj, NULL);
String8 name(nameChars);
env->ReleaseStringUTFChars(nameObj, nameChars);
sp<InputChannel> serverChannel;
sp<InputChannel> clientChannel;
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
}
在android_view_InputChannel_nativeOpenInputChannelPair函数中调用InputChannel::openInputChannelPair函数:
status_t InputChannel::openInputChannelPair(const String8& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
status_t result = -errno;
ALOGE("channel '%s' ~ Could not create socket pair. errno=%d",
name.string(), errno);
outServerChannel.clear();
outClientChannel.clear();
return result;
}
int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
String8 serverChannelName = name;
serverChannelName.append(" (server)");
outServerChannel = new InputChannel(serverChannelName, sockets[0]);
String8 clientChannelName = name;
clientChannelName.append(" (client)");
outClientChannel = new InputChannel(clientChannelName, sockets[1]);
return OK;
}
创建一对sockets,用于进程间通信。并创建一个outServerChannel,另一个outClientChannel。分别把sockets放入outServerChannel和outClientChannel中。然后返回去给serverChannel和clientChannel。
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
if (env->ExceptionCheck()) {
return NULL;
}
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(serverChannel));
if (env->ExceptionCheck()) {
return NULL;
}
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
new NativeInputChannel(clientChannel));
if (env->ExceptionCheck()) {
return NULL;
}
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
接着创建一个java用的InputChannel二维数组,分别用于存放java层创建出来的serverChannelObj和clientChannelObj。返回到addWindow后,InputChanne[0]先存入WindowState中,然后把InputChanne[1]传给java层的ViewRootImpl中。
public void transferTo(InputChannel outParameter) {
nativeTransferTo(outParameter);
}
调用(JNI)android_view_InputChannel.cpp中android_view_InputChannel_nativeTransferTo:
static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,
jobject otherObj) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
android_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel);
android_view_InputChannel_setNativeInputChannel(env, obj, NULL);
}
把nativeInputChannel地址放入outInputChannel类中的成员变量mPtr中。其中nativeInputChannel中包含有sockets。所以nativeInputChannel中InputChannel传给了java层ViewRootImpl中的mInputChannel中。
看看mInputManager.registerInputChannel函数
public void registerInputChannel(InputChannel inputChannel,
InputWindowHandle inputWindowHandle) {
nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
调用 (JNI)com_android_server_input_InputManagerService.cpp中
nativeRegisterInputChannel函数:
static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
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.cpp中registerInputChannel函数:
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
mLooper->wake();
return OK;
}
创建一个Connection,放入mConnectionsByFd队例中。前面《Android 5.0输入系统分析之InputDispatcher线程分析》中有从mConnectionsByFd中取出Connection,所以这Connection就是在这里放入mConnectionsByFd队例。从inputChannel中取出fd,然后调用 mLooper->addFd函数:
int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) {
int epollEvents = 0;
if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
{ // acquire lock
AutoMutex _l(mLock);
Request request;
request.fd = fd;
request.ident = ident;
request.callback = callback;
request.data = data;
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = epollEvents;
eventItem.data.fd = fd;
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex < 0) {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
mRequests.add(fd, request);
} else {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
mRequests.replaceValueAt(requestIndex, request);
}
} // release lock
return 1;
}
把fd,ident,callback等数据存入Request中。然后把fd加入epoll中监听。准备好后,用mLooper->wake()唤醒了InputDispatcher线程接收APP处理后返回来的信息,实际调用 pollOnce函数:
int Looper::pollInner(int timeoutMillis) {
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
Response& response = mResponses.editItemAt(i);
int callbackResult = response.request.callback->handleEvent(fd, events, data);
}
当接收到APP返回来的数据后,从mResponses中取出fd,ident,callback等数据,然后调用 callback函数,实际就是InputDispatcher.cpp中handleReceiveCallback函数:
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
InputDispatcher* d = static_cast<InputDispatcher*>(data);
{
ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
bool notify;
sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
for (;;) {
uint32_t seq;
bool handled;
status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
gotOne = true;
}
}
d->unregisterInputChannelLocked(connection->inputChannel, notify);
return 0; // remove the callback
}
}
从mConnectionsByFd队例中取出Connection,然后调用 Connection里的inputPublisher.receiveFinishedSignal来接收APP返回来的数据
status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {
InputMessage msg;
status_t result = mChannel->receiveMessage(&msg);
return OK;
}
调用 了InputTransport.cpp中receiveMessage函数:
status_t InputChannel::receiveMessage(InputMessage* msg) {
ssize_t nRead;
do {
nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
} while (nRead == -1 && errno == EINTR);
return OK;
}
用recv接收APP返回的数据存入InputMessage中。
status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
bool notify) {
ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
mConnectionsByFd.removeItemsAt(connectionIndex);
if (connection->monitor) {
removeMonitorChannelLocked(inputChannel);
}
mLooper->removeFd(inputChannel->getFd());
return OK;
}
完成后从mConnectionsByFd队例中删除Connection。可以知道 InputDispatcher线程做二件事,第一件事:从InputReader读到的数据分发给焦点窗口;第二件事:接收焦点窗口处理后返回的数据。那么焦点窗口是谁来接收,又由谁来处理,又怎么发给InputDispatcher线程?
继续向下分析ViewRootImpl.java中的setView函数。
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
创建一个WindowInputEventReceiver,调用WindowInputEventReceiver构造函数:
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
调用子InputEventReceiver的构造函数:
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
调用 (JNI)android_view_InputEventReceiver.cpp中nativeInit函数:
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
receiverWeak, inputChannel, messageQueue);
status_t status = receiver->initialize();
return reinterpret_cast<jlong>(receiver.get());
}
从java层获得一个InputChannel,上面有分析这个InputChannel。然后创建一个NativeInputEventReceiver,调用了NativeInputEventReceiver里的initialize函数:
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
调用:
void NativeInputEventReceiver::setFdEvents(int events) {
int fd = mInputConsumer.getChannel()->getFd();
mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
}
从InputChannel中取出fd,传给mMessageQueue->getLooper()->addFd,这个实际就是调用了Looper.cpp中addFd函数,addFd函数与上面有分析过addFd过程一样,这就不再分析了。
APP层会调用 Looper.cpp中pollOnce函数,pollOnce函数也是与上面pollOnce函数的分析一样,也是调用 callback函数里handleEvent,这个callback函数实际就是android_view_InputEventReceiver.cpp中handleEvent函数:
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
return 1;
}
调用android_view_InputEventReceiver.cpp中consumeEvents函数:
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
}
调用java层的InputEventReceiver.java中dispatchInputEvent函数:
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
最后调用WindowInputEventReceiver中onInputEvent函数:
public void onInputEvent(InputEvent event) { //onInputEvent
enqueueInputEvent(event, this, 0, true);
}
直接调用 enqueueInputEvent函数:
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
最后调用了doProcessInputEvents函数:
void doProcessInputEvents() {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
deliverInputEvent(q);
}
从队例头中取出数据,调用deliverInputEvent函数处理
private void deliverInputEvent(QueuedInputEvent q) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
从q.shouldSkipIme()检查是第一次的还是上一次的,如果InputStage存在,那么调用deliver函数:
public final void deliver(QueuedInputEvent q) {
if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
forward(q);
} else if (shouldDropInputEvent(q)) {
finish(q, false);
} else {
apply(q, onProcess(q));
}
}
检查是否处理了,如果处理了调用 forward函数,如果处理完成了调用finish函数,否则没处理,调用onProcess函数:
protected int onProcess(QueuedInputEvent q) {
return FORWARD;
}
最终APP调用 了onProcess函数来处理。