handleReceiveCallback 方法对消息进行处理。
上一节打通了 InputDispatcher 和输入窗口之间双向的通道,这是通过 InputChannel 承载的。现在可以继续分析从 InputDispatcher 发送出的事件如何被接收处理了。
NativeInputEventReceiver 类 handleEvent 被调用,用来处理 InputDispatcher 发送来的事件。
frameworks/base/core/jni/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;
}
......
return 1;
}
- 调用 InputConsumer 类 consume 方法接收输入事件(InputEvent)
- 调用 android_view_KeyEvent_fromNative 将 InputEvent 转化为 jobject 供 Java 层使用
- Native 调用 Java InputEventReceiver 类 dispatchInputEvent 方法转入 Java 层处理
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
......
bool skipCallbacks = false;
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
......
if (!skipCallbacks) {
if (!receiverObj.get()) {
receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
if (!receiverObj.get()) {
ALOGW("channel '%s' ~ Receiver object was finalized "
"without being disposed.", getInputChannelName());
return DEAD_OBJECT;
}
}
......
jobject inputEventObj;
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY:
......
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast<KeyEvent*>(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION: {
......
break;
}
default:
assert(false); // InputConsumer should prevent this from ever happening
inputEventObj = NULL;
}
if (inputEventObj) {
......
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching input event.");
skipCallbacks = true;
}
env->DeleteLocalRef(inputEventObj);
} else {
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
skipCallbacks = true;
}
}
if (skipCallbacks) {
mInputConsumer.sendFinishedSignal(seq, false);
}
}
}
- 调用客户端 InputChannel receiveMessage 接收新消息
- initializeKeyEvent 方法中把接收来的消息(InputMessage)转化为 KeyEvent
frameworks/native/libs/input/InputTransport.cpp
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
......
*outSeq = 0;
*outEvent = NULL;
// 获取下一条输入消息。
while (!*outEvent) {
if (mMsgDeferred) {
......
} else {
// 收到新消息。
status_t result = mChannel->receiveMessage(&mMsg);
......
}
switch (mMsg.header.type) {
case InputMessage::TYPE_KEY: {
KeyEvent* keyEvent = factory->createKeyEvent();
if (!keyEvent) return NO_MEMORY;
// 将 InputMessage 转化为 KeyEvent
initializeKeyEvent(keyEvent, &mMsg);
*outSeq = mMsg.body.key.seq;
*outEvent = keyEvent;
......
break;
}
case AINPUT_EVENT_TYPE_MOTION: {
......
}
default:
ALOGE("channel '%s' consumer ~ Received unexpected message of type %d",
mChannel->getName().string(), mMsg.header.type);
return UNKNOWN_ERROR;
}
}
return OK;
}
InputConsumer 成员变量 mChannel(InputChannel)调用 receiveMessage 接收消息,最终会使用 sys/socket.h 头文件中定义的 recv 方法。
frameworks/native/libs/input/InputTransport.cpp
status_t InputChannel::receiveMessage(InputMessage* msg) {
ssize_t nRead;
do {
nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
} while (nRead == -1 && errno == EINTR);
if (nRead < 0) {
int error = errno;
......
if (error == EAGAIN || error == EWOULDBLOCK) {
return WOULD_BLOCK;
}
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
return DEAD_OBJECT;
}
return -error;
}
if (nRead == 0) { // check for EOF
......
return DEAD_OBJECT;
}
if (!msg->isValid(nRead)) {
......
return BAD_VALUE;
}
......
return OK;
}
initializeKeyEvent 非常简单,进一步调用 KeyEvent 类 initialize 方法初始化,做了一些简单的成员变量赋值处理。
frameworks/native/libs/input/InputTransport.cpp
void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) {
event->initialize(
msg->body.key.deviceId,
msg->body.key.source,
msg->body.key.action,
msg->body.key.flags,
msg->body.key.keyCode,
msg->body.key.scanCode,
msg->body.key.metaState,
msg->body.key.repeatCount,
msg->body.key.downTime,
msg->body.key.eventTime);
}
接下来分析 Native 调用 Java InputEventReceiver 类 dispatchInputEvent 方法转入 Java 层处理。实际调用 Java 类 WindowInputEventReceiver dispatchInputEvent 方法。我们在前一节中得知构造 NativeInputEventReceiver 对象时传递来一个弱引用(WindowInputEventReceiver),然后将其提升为全局引用赋值给了 mReceiverWeakGlobal。Native CallVoidMethod 调用的时候派上了用场。
frameworks/base/core/java/android/view/InputEventReceiver.java
public abstract class InputEventReceiver {
......
// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
......
}
此处 onInputEvent 工作实际是由 enqueueInputEvent 完成的。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
......
}
......
}
- 获取 QueuedInputEvent 对象
- 调用 doProcessInputEvents 处理事件
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
adjustInputEventForCompatibility(event);
// 获取 QueuedInputEvent 对象
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
// 始终按顺序将输入事件排入队列,而不考虑其时间戳。
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
// 未处理的输入事件计数
mPendingInputEventCount += 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
// 此处 processImmediately 为 true
if (processImmediately) {
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
......
}
doProcessInputEvents 函数中通过一个 while 循环调用 deliverInputEvent 函数处理所有输入事件。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
void doProcessInputEvents() {
// 在队列中传递所有未处理的输入事件。
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);
long eventTime = q.mEvent.getEventTimeNano();
long oldestEventTime = eventTime;
......
deliverInputEvent(q);
}
// 我们已经处理完所有现在可以处理的输入事件,因此我们可以立即清除待处理标志。
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}
......
}
deliverInputEvent 方法中涉及一个新的类 InputStage,继续传递输入事件之前,必须要搞清楚它做了什么?
假如 q.shouldSkipIme() 返回 false,那么输入事件沿着 InputStage 链处理,直到某个 InputStage 可以处理事件。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
private void deliverInputEvent(QueuedInputEvent q) {
......
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
......
}
mSyntheticInputStage、mFirstPostImeInputStage 和 mFirstInputStage 这三个成员变量都是在 ViewRootImpl 类 setView 方法中赋值的。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
......
// 设置输入管道。
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
......
}
}
}
......
}
InputStage —— 基类,用于实现责任链中处理输入事件的 Stage。事件通过 deliver 方法传递到 Stage 上。然后,该 Stage 可以选择完成事件或将其转发到下一个 Stage。
SyntheticInputStage —— 从未处理的输入事件执行新输入事件的合成。
ViewPostImeInputStage —— 将 post-ime 输入事件传递到视图层次结构。
AsyncInputStage —— 用于实现支持异步和无序处理输入事件的输入管道 Stage 的基类。除了正常的 InputStage 可以做的事情之外,异步 InputStage 还可以延迟已经交付给它的输入事件,并稍后完成或转发它。
NativePostImeInputStage —— 将 post-ime 输入事件传递到 Native Activity。
EarlyPostImeInputStage —— 执行 post-ime 输入事件的早期处理。
ImeInputStage —— 向 ime 交付输入事件。不支持指针事件。
ViewPreImeInputStage —— 将 pre-ime 输入事件交付给视图层次结构。不支持指针事件。
NativePreImeInputStage —— 将 pre-ime 输入事件交付给 Native Activity。不支持指针事件。
这些类之间关系如下:
InputStage 包含一个 mNext 成员,这将所有的 InputStage 链接成单链表。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
abstract class InputStage {
private final InputStage mNext;
......
/**
* 创建 InputStage
* @param next 事件应该被转发到的下一个 InputStage。
*/
public InputStage(InputStage next) {
mNext = next;
}
......
}
......
}
下面是 mSyntheticInputStage、mFirstPostImeInputStage 和 mFirstInputStage 在处理链表中的位置。
现在转到 stage.deliver(q) 处理输入事件。这会沿着 InputStage 逐个调用,直到有一个 InputStage 处理完成输入事件,最后到达链表尾,调用 finishInputEvent 结束流程。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
abstract class InputStage {
......
/**
* 传递要处理的事件。
*/
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));
}
}
/**
* 将输入事件标记为已完成,然后将其转发到下一个 Stage。
*/
protected void finish(QueuedInputEvent q, boolean handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
if (handled) {
q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
}
forward(q);
}
/**
* 将事件转发到下一个 Stage。
*/
protected void forward(QueuedInputEvent q) {
onDeliverToNext(q);
}
/**
* 将来自 onProcess 的结果码应用于指定的事件。
*/
protected void apply(QueuedInputEvent q, int result) {
if (result == FORWARD) {
forward(q);
} else if (result == FINISH_HANDLED) {
finish(q, true);
} else if (result == FINISH_NOT_HANDLED) {
finish(q, false);
} else {
throw new IllegalArgumentException("Invalid result: " + result);
}
}
/**
* 准备处理事件时调用。
* @return 指示如何处理事件的结果码。
*/
protected int onProcess(QueuedInputEvent q) {
return FORWARD;
}
/**
* 当事件被传递到下一个 Stage 时调用。
*/
protected void onDeliverToNext(QueuedInputEvent q) {
if (DEBUG_INPUT_STAGES) {
Log.v(TAG, "Done with " + getClass().getSimpleName() + ". " + q);
}
if (mNext != null) {
mNext.deliver(q);
} else {
finishInputEvent(q);
}
}
......
}
......
}
假设现在需要将键盘按键事件传递到当前窗口处理。那么最终会在 ViewPostImeInputStage 类 onProcess 方法中处理。
onProcess 方法判断是否为按键事件然后交由 processKeyEvent 进一步处理。processKeyEvent 函数中调用了相应 View 的 dispatchKeyEvent 方法,进行事件分发,这就把输入事件派发到了当前窗口了!
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
final class ViewPostImeInputStage extends InputStage {
public ViewPostImeInputStage(InputStage next) {
super(next);
}
@Override
protected int onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) {
return processKeyEvent(q);
} else {
......
}
}
@Override
protected void onDeliverToNext(QueuedInputEvent q) {
......
super.onDeliverToNext(q);
}
private int processKeyEvent(QueuedInputEvent q) {
final KeyEvent event = (KeyEvent)q.mEvent;
......
// 将按键交付给视图层次结构。
if (mView.dispatchKeyEvent(event)) {
return FINISH_HANDLED;
}
// 是否需要删除输入事件
if (shouldDropInputEvent(q)) {
return FINISH_NOT_HANDLED;
}
// 快捷键处理
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.isCtrlPressed()
&& event.getRepeatCount() == 0
&& !KeyEvent.isModifierKey(event.getKeyCode())) {
if (mView.dispatchKeyShortcutEvent(event)) {
return FINISH_HANDLED;
}
if (shouldDropInputEvent(q)) {
return FINISH_NOT_HANDLED;
}
}
// 应用回退事件策略。
if (mFallbackEventHandler.dispatchKeyEvent(event)) {
return FINISH_HANDLED;
}
if (shouldDropInputEvent(q)) {
return FINISH_NOT_HANDLED;
}
// 处理自动焦点更改。
if (event.getAction() == KeyEvent.ACTION_DOWN) {
int direction = 0;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_LEFT:
if (event.hasNoModifiers()) {
direction = View.FOCUS_LEFT;
}
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (event.hasNoModifiers()) {
direction = View.FOCUS_RIGHT;
}
break;
case KeyEvent.KEYCODE_DPAD_UP:
if (event.hasNoModifiers()) {
direction = View.FOCUS_UP;
}
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
if (event.hasNoModifiers()) {
direction = View.FOCUS_DOWN;
}
break;
case KeyEvent.KEYCODE_TAB:
if (event.hasNoModifiers()) {
direction = View.FOCUS_FORWARD;
} else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
direction = View.FOCUS_BACKWARD;
}
break;
}
if (direction != 0) {
View focused = mView.findFocus();
if (focused != null) {
View v = focused.focusSearch(direction);
if (v != null && v != focused) {
// 进行数学运算,将先前关注的焦点区域变成新焦点的视图坐标系
focused.getFocusedRect(mTempRect);
if (mView instanceof ViewGroup) {
((ViewGroup) mView).offsetDescendantRectToMyCoords(
focused, mTempRect);
((ViewGroup) mView).offsetRectIntoDescendantCoords(
v, mTempRect);
}
if (v.requestFocus(direction, mTempRect)) {
// 播放音效
playSoundEffect(SoundEffectConstants
.getContantForFocusDirection(direction));
return FINISH_HANDLED;
}
}
// 给焦点视图最后一次机会来处理 dpad 键。
if (mView.dispatchUnhandledMove(focused, direction)) {
return FINISH_HANDLED;
}
} else {
View v = focusSearch(null, direction);
if (v != null && v.requestFocus(direction)) {
return FINISH_HANDLED;
}
}
}
}
return FORWARD;
}
......
}
......
}
输入按键事件处理完成以后就会调用 ViewRootImpl 类的 finishInputEvent 方法。
QueuedInputEvent 类的成员变量 mReceiver 是在 enqueueInputEvent 方法中调用 obtainQueuedInputEvent 函数传入的 WindowInputEventReceiver 对象。事件已经处理完成,所以 handled = true,接着就会调用 WindowInputEventReceiver 类 finishInputEvent 方法,此方法实现在其父类 InputEventReceiver 中。
frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
......
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 {
......
}
recycleQueuedInputEvent(q);
}
......
}
- 判断入参是否满足条件,不满足条件(event)抛出异常,或在 Log 系统打印警告信息(mReceiverPtr)
- 将 seq 从 mSeqMap 中移除
- 调用 nativeFinishInputEvent 进一步处理
frameworks/base/core/java/android/view/InputEventReceiver.java
public abstract class InputEventReceiver {
......
private static native void nativeFinishInputEvent(long receiverPtr, int seq, boolean handled);
......
public final void finishInputEvent(InputEvent event, boolean handled) {
if (event == null) {
throw new IllegalArgumentException("event must not be null");
}
if (mReceiverPtr == 0) {
Log.w(TAG, "Attempted to finish an input event but the input event "
+ "receiver has already been disposed.");
} else {
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();
}
......
}
- receiverPtr 强转为 NativeInputEventReceiver 对象
- 调用 NativeInputEventReceiver 类 finishInputEvent 方法
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
jint seq, jboolean handled) {
sp<NativeInputEventReceiver> receiver =
reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
status_t status = receiver->finishInputEvent(seq, handled);
if (status && status != DEAD_OBJECT) {
String8 message;
message.appendFormat("Failed to finish input event. status=%d", status);
jniThrowRuntimeException(env, message.string());
}
}
调用 InputConsumer 类 sendFinishedSignal 发送完成信号
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
......
status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
......
return status;
}
- 首先发送批序列链的完成信号
- 发送批处理中的最后一条消息的完成信号
frameworks/native/libs/input/InputTransport.cpp
status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
......
size_t seqChainCount = mSeqChains.size();
// 首先发送批序列链的完成信号。
if (seqChainCount) {
uint32_t currentSeq = seq;
uint32_t chainSeqs[seqChainCount];
size_t chainIndex = 0;
for (size_t i = seqChainCount; i-- > 0; ) {
const SeqChain& seqChain = mSeqChains.itemAt(i);
if (seqChain.seq == currentSeq) {
currentSeq = seqChain.chain;
chainSeqs[chainIndex++] = currentSeq;
mSeqChains.removeAt(i);
}
}
status_t status = OK;
while (!status && chainIndex-- > 0) {
status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
}
if (status) {
// 一个错误发生了,所以至少有一个信号没有发送,重建链。
do {
SeqChain seqChain;
seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
seqChain.chain = chainSeqs[chainIndex];
mSeqChains.push(seqChain);
} while (chainIndex-- > 0);
return status;
}
}
// 发送批处理中的最后一条消息的完成信号。
return sendUnchainedFinishedSignal(seq, handled);
}
首先将 seq 和 handled 打包到 InputMessage 中,使用 InputChannel (mChannel)对象的 sendMessage 方法将消息发给 InputDispatcher。
frameworks/native/libs/input/InputTransport.cpp
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);
}
由于客户端 Socket 写入数据,Looper 被唤醒就会执行 InputDispatcher 类 handleReceiveCallback 方法。
- mConnectionsByFd 取出 Connection
- 调用 Connection 类成员变量 inputPublisher 的 receiveFinishedSignal 方法接收消息
- 调用 InputDispatcher 类 finishDispatchCycleLocked 方法
- 调用 runCommandsLockedInterruptible 执行命令(Commond)
frameworks/native/services/inputflinger/InputDispatcher.cpp
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
InputDispatcher* d = static_cast<InputDispatcher*>(data);
{ // acquire lock
AutoMutex _l(d->mLock);
ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
if (connectionIndex < 0) {
ALOGE("Received spurious receive callback for unknown input channel. "
"fd=%d, events=0x%x", fd, events);
return 0; // remove the callback
}
bool notify;
sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
if (!(events & ALOOPER_EVENT_INPUT)) {
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
"events=0x%x", connection->getInputChannelName(), events);
return 1;
}
nsecs_t currentTime = now();
bool gotOne = false;
status_t status;
for (;;) {
uint32_t seq;
bool handled;
status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
if (status) {
break;
}
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
gotOne = true;
}
if (gotOne) {
d->runCommandsLockedInterruptible();
if (status == WOULD_BLOCK) {
return 1;
}
}
......
} else {
......
}
......
} // release lock
}
从服务端 InputChannel 读取发来的消息
frameworks/native/libs/input/InputTransport.cpp
status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandled) {
......
InputMessage msg;
status_t result = mChannel->receiveMessage(&msg);
if (result) {
*outSeq = 0;
*outHandled = false;
return result;
}
if (msg.header.type != InputMessage::TYPE_FINISHED) {
ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",
mChannel->getName().string(), msg.header.type);
return UNKNOWN_ERROR;
}
*outSeq = msg.body.finished.seq;
*outHandled = msg.body.finished.handled;
return OK;
}
finishDispatchCycleLocked 方法中调用 onDispatchCycleFinishedLocked。
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, uint32_t seq, bool handled) {
......
connection->inputPublisherBlocked = false;
if (connection->status == Connection::STATUS_BROKEN
|| connection->status == Connection::STATUS_ZOMBIE) {
return;
}
// 通知其他系统组件并准备开始下一个调度周期。
onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
}
调用 postCommandLocked 方法,其入参是个函数指针 InputDispatcher::doDispatchCycleFinishedLockedInterruptible。然后将返回的 CommandEntry 对应成员变量赋值。
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::onDispatchCycleFinishedLocked(
nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
commandEntry->connection = connection;
commandEntry->eventTime = currentTime;
commandEntry->seq = seq;
commandEntry->handled = handled;
}
将 Command(函数指针)包装成 CommandEntry,并添加到 mCommandQueue 队列尾部,然后返回这个 CommandEntry 对象。
frameworks/native/services/inputflinger/InputDispatcher.cpp
InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
CommandEntry* commandEntry = new CommandEntry(command);
mCommandQueue.enqueueAtTail(commandEntry);
return commandEntry;
}
Command 函数指针定义如下。
frameworks/native/services/inputflinger/InputDispatcher.h
class InputDispatcher : public InputDispatcherInterface {
......
private:
......
typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
......
}
- 从 Connection 中取出所反馈的事件
- 事件是否超时,超时记录一个警告
- 从 waitQueue 中删除所反馈的事件
- 启动此连接的下一个分发周期
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
CommandEntry* commandEntry) {
sp<Connection> connection = commandEntry->connection;
nsecs_t finishTime = commandEntry->eventTime;
uint32_t seq = commandEntry->seq;
bool handled = commandEntry->handled;
// 处理事件后策略操作。
DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
if (dispatchEntry) {
nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
// 当事件处理时间超过 2s 时,即使没有发生 ANR,也要记录一个警告。
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
String8 msg;
msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ",
connection->getWindowName(), eventDuration * 0.000001f);
dispatchEntry->eventEntry->appendDescription(msg);
ALOGI("%s", msg.string());
}
bool restartEvent;
......
// 退出事件队列并开始下一个循环。
// 注意,由于锁可能已经释放,等待队列的内容可能已经空,因此我们需要重复检查一些事情。
if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
// 从 waitQueue 移除对应的 DispatchEntry
connection->waitQueue.dequeue(dispatchEntry);
traceWaitQueueLengthLocked(connection);
if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
connection->outboundQueue.enqueueAtHead(dispatchEntry);
traceOutboundQueueLengthLocked(connection);
} else {
// 释放 DispatchEntry 对象
releaseDispatchEntryLocked(dispatchEntry);
}
}
// 启动此连接的下一个分发周期。
startDispatchCycleLocked(now(), connection);
}
}
最后谈一谈何时运行添加到 mCommandQueue 中的命令?这是在 dispatchOnce() 方法中。
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
......
// 运行所有挂起的命令(如果有的话)。如果运行了任何命令,则强制立即唤醒下一个轮询。
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
......
}
- while 循环中从 mCommandQueue 逐个取出 CommandEntry
- 运行包装在 CommandEntry 中的 Command 函数指针指向的函数,以上 InputDispatcher::doDispatchCycleFinishedLockedInterruptible 函数就会被执行
- 释放 CommandEntry (commandEntry)对象
frameworks/native/services/inputflinger/InputDispatcher.cpp
bool InputDispatcher::runCommandsLockedInterruptible() {
if (mCommandQueue.isEmpty()) {
return false;
}
do {
CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
Command command = commandEntry->command;
(this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
commandEntry->connection.clear();
delete commandEntry;
} while (! mCommandQueue.isEmpty());
return true;
}
另外在 handleReceiveCallback 函数中,也执行了 runCommandsLockedInterruptible 处理命令。
画流程图总结一下。
最后总结一下输入系统中各种队列中事件是如何流向的。