Android 源码 输入系统之事件窗口分发

468 阅读11分钟

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;
}
  1. 调用 InputConsumer 类 consume 方法接收输入事件(InputEvent)
  2. 调用 android_view_KeyEvent_fromNative 将 InputEvent 转化为 jobject 供 Java 层使用
  3. 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);
        }
    }
}
  1. 调用客户端 InputChannel receiveMessage 接收新消息
  2. 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);
        }
        ......
    }
    ......
}
  1. 获取 QueuedInputEvent 对象
  2. 调用 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);
    }
    ......
}
  1. 判断入参是否满足条件,不满足条件(event)抛出异常,或在 Log 系统打印警告信息(mReceiverPtr)
  2. 将 seq 从 mSeqMap 中移除
  3. 调用 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();
    }
    ......
}
  1. receiverPtr 强转为 NativeInputEventReceiver 对象
  2. 调用 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;
}
  1. 首先发送批序列链的完成信号
  2. 发送批处理中的最后一条消息的完成信号

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 方法。

  1. mConnectionsByFd 取出 Connection
  2. 调用 Connection 类成员变量 inputPublisher 的 receiveFinishedSignal 方法接收消息
  3. 调用 InputDispatcher 类 finishDispatchCycleLocked 方法
  4. 调用 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);
    ......
}
  1. 从 Connection 中取出所反馈的事件
  2. 事件是否超时,超时记录一个警告
  3. 从 waitQueue 中删除所反馈的事件
  4. 启动此连接的下一个分发周期

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
    ......
}
  1. while 循环中从 mCommandQueue 逐个取出 CommandEntry
  2. 运行包装在 CommandEntry 中的 Command 函数指针指向的函数,以上 InputDispatcher::doDispatchCycleFinishedLockedInterruptible 函数就会被执行
  3. 释放 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 处理命令。

画流程图总结一下。
在这里插入图片描述

最后总结一下输入系统中各种队列中事件是如何流向的。
在这里插入图片描述