这篇文章补充了之前文章中没有的view初始化的流程分析。本文详细的分析了input event是通过何种方式传递到activity以及从驱动中读取到event后,jni是如何对按键进行上报的过程。通过本文的分析,能够基本上了解按键的整个传递过程。
在启动一个activity时将会调用ViewRootImpl.setView()函数。下面将这个函数中的主要部分给出:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
····
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
//这个对应client端,将InputEvent传递给view
mInputChannel = new InputChannel();
}
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mInputChannel);
} catch (RemoteException e) {}
···
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
//mInputChannel注册到native层
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
···
}
上面段代码中主要进行了三个动作:
1.创建一个Java层的InputChannel,这个InputChannel后面用来创建两个socket,一个是client端,app使用它接收按键信息;一个是server端,底层将按键信息写入server端
2.调用WindowSession.addToDisplay,向系统中添加session
3.注册WindowInputEventReceiver,当client端有消息时,通知view来消息。
下面看一下WindowSession.addToDisplay的实现
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets,
InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outInputChannel);
}
这里面的mService实际上就是WindowManagerService
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, InputChannel outInputChannel) {
win = new WindowState(this, session, client, token, attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
if (outInputChannel != null && (attrs.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
String name = win.makeInputChannelName();//这个就是创建一个关于这个view的字符串
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);//调用InputChannel创建两个socket
win.setInputChannel(inputChannels[0]);//server channel
inputChannels[1].transferTo(outInputChannel);//client channel 将Native层的对象转换成Java层的对象
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);//将server socket注册到底层
}
}
下面看一下这个registerInputChannel函数的实现。
InputManangerService.java
public void registerInputChannel(InputChannel inputChannel,
InputWindowHandle inputWindowHandle) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
com_android_server_iinput_InputManagerService.cpp
static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
jint ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);//获取native层的InputManager
···
status_t status = im->registerInputChannel( env, inputChannel, inputWindowHandle, monitor);
···
}
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
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
{ // acquire lock
AutoMutex _l(mLock);
//检查这个channel是否存在
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);
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);
if (monitor) {
mMonitoringChannels.push(inputChannel);
}
//将这个fd注册到looper中。用来接收来自framework层的消息,并且调用handleReceiveCallback进行处理
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
return OK;
}
至此就已经将Server端的socket注册到了Looper中了。至于addFd函数的实现,请参考Native层的Looper.cpp。
Client端socket注册实在创建WindowInputEventReceiver对象时注册的。
下面看一下 WindowInputEventReceiver类
ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {}
InputEventReceiver.java
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
在初始化函数时就会调用nativeInit JNI函数。
android_view_InputEventReceiver.cpp
static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
jobject inputChannelObj, jobject messageQueueObj) {
//将java层的对象转换成c中的对象
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();
}
android_view_InputEventReceiver.cpp
NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
jobject receiverWeak, const sp<InputChannel>& inputChannel,
const sp<MessageQueue>& messageQueue) :
mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
mInputConsumer(inputChannel), mMessageQueue(messageQueue),
mBatchedInputEventPending(false), mFdEvents(0) {
}
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
上面就是将mInputConsumer的中Channel的fd注册到looper中。其中Channel就是传递下来的client端的socket。至此client端的socket也已经注册完毕。后面就是利用Server/Client socket进行通讯,实现按键信息的传递。
EventHub用来读取驱动中的event。InputReader负责将EventHub中的消息读取出来,之后InputDispatcher将event发送出来。
具体代码如下
InputReader.cpp
void InputReader::loopOnce() {
···
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);//读取event
···
processEventsLocked(mEventBuffer, count);//处理event事件
···
}
这里处理的event事件有以下四种情况:
1.DEVICE_ADDED添加输入设备
2.DEVICE_REMOVED移除输入设备
3.FINISHED_DEVICE_SCAN输入设备扫描完成
4.普通按键
这里我们只对普通按键过程进行分析
InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
···
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
···
}
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);//查找event对应的设备
InputDevice* device = mDevices.valueAt(deviceIndex);//获取deviceid对应的设备
device->process(rawEvents, count);//调用设备的处理函数
}
这里我们以KeyboardInputMapper为例
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)){}//获取按键的keycode
processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
break;
···
}
}
}
void KeyboardInputMapper::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);//这个call InputDispatcher.notifyKey
···
}
这个里面会调用InputDispatcher里面的notifyKey函数。
InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
···
event.initialize(args->deviceId, args->source, args->action,
flags, args->keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
//这里面要先call PhoneWindowManager中的interceptKeyBeforeQueueing
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
···
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, args->keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
//然后将这个keyevent放到list中
needWake = enqueueInboundEventLocked(newEntry);//将这个event放入到队列中,供后面进行处理(1)
if (needWake) {//这个会唤醒dispatcher loop.也就是会调dispatchOnce
mLooper->wake();
}
}
这里需要注意,PhoneWindowManager里面的interceptKeyBeforeQueueing实在这个阶段调用的。这时候还没加入到queue中。
将Event加入到Queue中之后还要对queue进行处理。后面调用mLooper->wake()的目的就是开始后续的处理。
void InputDispatcher::dispatchOnce() {
if (!haveCommandsLocked()) {
ALOGE("no commands");
dispatchOnceInnerLocked(&nextWakeupTime);//将从driver中收到的event &command封装到一个结构中。并且放到command队列中
}
//此时应该已经将要执行的command放入到了queue中。下面就是将上面放入的event使用command进行事件的处理
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}
这个函数比较有意思,下面详细分析一下
先看haveCommandsLocked函数
bool InputDispatcher::haveCommandsLocked() const {
return !mCommandQueue.isEmpty();
}
这个函数看是否已经存才command,第一次执行会返回false。
下面看dispatchOnceInnerLocked
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
···
case EventEntry::TYPE_KEY: {
···
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
···
}
···
}
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
//KeyEntry初始化INTERCEPT_KEY_RESULT_UNKNOWN
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {//当有event 第一次到达时就会走这里
//这里注册的command将会再dispatchOnce函数里面的runCommandsLockedInterruptible进行处理
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);//
if (mFocusedWindowHandle != NULL) {
commandEntry->inputWindowHandle = mFocusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
return false; // wait for the command to run
} else {
···
}
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
···
}
···
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,entry, inputTargets, nextWakeupTime);//这个函数用来查找有哪些对象已经建立了connection。event将会发送给所有的注册进来的对象。也就是activity。
···
dispatchEventLocked(currentTime, entry, inputTargets);
···
}
postCommandLocked函数就是向mCommandQueue中添加command的实现如下:
InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
CommandEntry* commandEntry = new CommandEntry(command);
mCommandQueue.enqueueAtTail(commandEntry);
return commandEntry;
}
执行完这个函数只有command queue中已经存在command,但是还没执行。
下面继续分析
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
pokeUserActivityLocked(eventEntry);//用来决定是否要唤醒设备或者点亮屏幕,最终调用的是PowerManagerService。
//下面将会通知所有注册进来的channen,有event发生了。
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<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
} else {
···
}
}
}
下面的调用顺序为:prepareDispatchCycleLocked-> enqueueDispatchEntriesLocked &startDispatchCycleLocked
这里面有个小的细节说明一下:enqueueDispatchEntriesLocked函数会调用enqueueDispatchEntryLocked函数。
void InputDispatcher::enqueueDispatchEntryLocked(
const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
int32_t dispatchMode) {
···
DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
inputTarget->scaleFactor);
···
connection->outboundQueue.enqueueAtTail(dispatchEntry);
···
}
这里会封装DispatchEntry,之后放到connection,也就是server socket的封装对象的outboundQueue中。那么在后面发送的时候就会从这里面取event。
继续后面的分析
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
···
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
// Publish the key event.
// call InputTransport.cpp
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;
}
···
}
这里会调用InputTransport中的publishKeyEvent
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) {
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);
}
status_t InputChannel::sendMessage(const InputMessage* msg) {
···
do {
nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
···
}
也就是调用socket的send函数。这里的mFd对应的是Server端的socket。
由于Server/client的socket是通过socketpair的方式打开的,所以向Server端socket写入数据时,client端的socket就能读取数据。
根据之前的分析可知client端的socket加入到了epoll中ALOOPER_EVENT_INPUT。所以它将会从epoll中返回。
处理代码
android_view_InputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
···
if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
···
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);//调用InputManagerService.dispatchInputEvent
···
···
}
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
···
for (;;) {
status_t status = mInputConsumer.consume(&mInputEventFactory, consumeBatches, frameTime, &seq, &inputEvent);
}
···
}
InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
while (!*outEvent) {
status_t result = mChannel->receiveMessage(&mMsg);
}
···
switch (mMsg.header.type) {
case InputMessage::TYPE_KEY: {
KeyEvent* keyEvent = factory->createKeyEvent();
if (!keyEvent) return NO_MEMORY;
initializeKeyEvent(keyEvent, &mMsg);
*outSeq = mMsg.body.key.seq;
*outEvent = keyEvent;
break;
}
···
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);//调用InputManagerService.dispatchInputEvent
···
}
看到在获取完event之后就调用了dispatchInputEvent。由前面的分析可以知道,在新的view生成之后,注册client socket时创建了WindowInputEventReceiver,这个类是继承自InputEventReceiver。所以这里面调用的dispatchInputEvent就是WindowInputEventReceiver。根据类的继承关系,在dispatchInputEvent中会调用onInputEvent。
接下来的就是在ViewRootImpl中对event进行处理。
ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
···
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
···
}
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
//将event加入到队列中
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
mPendingInputEventCount += 1;
//处理event
if (processImmediately) {
doProcessInputEvents();//处理event
} else {
scheduleProcessInputEvents();
}
}
void doProcessInputEvents() {
// Deliver all pending input events in the queue.
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;
mPendingInputEventCount -= 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
deliverInputEvent(q);
}
···
}
//决定应该是传递给那个stage,之后调用stage.deliver()开始处理input event。
private void deliverInputEvent(QueuedInputEvent q) {
InputStage stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
通过上面的分析可以发现,jni层获取到消息之后,会传递给framework层的InputEventReceiver。之后交给ViewRootImpl中的stage进行按键的处理。下面对stage进行一下分析
这里面的Stage是一个逻辑结构,类似于StateMachine。当有InputEvent之后将会传递到这个结构中进行处理。处理完成之后,会调用finishInputEvent函数来通知jni层,这个event已经处理完成。
各个Stage之间的关系如下图所示:
graph TD;
NativePreImeInputStage-->ViewPreImeInputStage;
ViewPreImeInputStage-->ImeInputStage;
ImeInputStage-->EarlyPostImeInputStage;
EarlyPostImeInputStage-->NativePostImeInputStage;
NativePostImeInputStage-->ViewPostImeInputStage;
ViewPostImeInputStage-->SyntheticInputStage;
指定的初始化stage
mFirstInputStage = nativePreImeStage;//按键处理的第一个stage
mFirstPostImeInputStage = earlyPostImeStage;
根据打印的log看,当接收到遥控器按键时将会调用mView.dispatchKeyEvent(),而这里的mView就是在创建Activity是通过setView设置进来的。当这个InputEvent事件处理完成之后,会调用finishInputEvent函数。
ViewRootImpl.java
private void finishInputEvent(QueuedInputEvent q) {
if (q.mReceiver != null) {
boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
q.mReceiver.finishInputEvent(q.mEvent, handled);
} else {
q.mEvent.recycleIfNeededAfterDispatch();
}
recycleQueuedInputEvent(q);
}
public final void finishInputEvent(InputEvent event, boolean handled) {
int index = mSeqMap.indexOfKey(event.getSequenceNumber());
if (index < 0) {
Log.w(TAG, "Attempted to finish an input event that is not in progress.");
} else {
int seq = mSeqMap.valueAt(index);
mSeqMap.removeAt(index);
nativeFinishInputEvent(mReceiverPtr, seq, handled);
}
event.recycleIfNeededAfterDispatch();
}
看到,会调用nativeFinishInputEvent进行处理,也就是会调用NativeInputEventReceiver.finishInputEvent()处理。
android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
···
status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
···
}
这里面的mInputConsumer与之前发送InputEvent是一样的,
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
···
return sendUnchainedFinishedSignal(seq, handled);
}
status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
InputMessage msg;
msg.header.type = InputMessage::TYPE_FINISHED;
msg.body.finished.seq = seq;
msg.body.finished.handled = handled;
return mChannel->sendMessage(&msg);
}
通过这部分代码,可以看出最后是通过client端的socket,将finish事件发送给jni层中的server端的。前面的分析可以知道,在注册server端的socket时,将socket注册到epoll中,并且指定有event时的处理函数为handleReceiveCallback。
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
//根据fd查找到对应的connection
ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
···
//开始下一轮的dispatch
status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
if (gotOne) {
d->runCommandsLockedInterruptible();
if (status == WOULD_BLOCK) {
return 1;
}
}
···
d->unregisterInputChannelLocked(connection->inputChannel, notify);
}
至此,InputEvent的整个处理过程已经完全结束。
Input event事件的处理,大概流程如下:
1.EventHub从驱动中获取InputEvent
2.InputReader从EventHub中读取数据发送给InputDispatcher
3.InputDispatcher发送给InputTransport,
4.InputTransport将消息发送给framework层的ViewRootImpl
5.ViewRootImpl对事件进行处理,完成之后发送finish给native层,用来启动下一轮的dispatch
事件是通过注册到epoll中的Server/Client sockets进行传递的。
发送event时会发送到所有的channel中的。
这里有个地方需要注意一下:
1.收到input event之后,先调用notifyKey->interceptKeyBeforeQueueing进行处理。这里的意思时native层中还没有加到command queue。
2.加入到队列之后调用runCommandsLockedInterruptible->interceptKeyBeforeDispatching进行处理,此时event已经加入到了command queue中了。
3.之后就时通过注册进来的InputChannel通知上层activity或者PhoneWindowManagerService