Android 输入事件分发全流程梳理(一)

1. 输入服务初始化

在系统进程system_server启动时,会在startOtherServices里面启动优先级较低的系统服务,其中包括了管理输入事件的系统服务InputManagerService

SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
    InputManagerService inputManager = null;
    ...
    inputManager = new InputManagerService(context);
}
InputManagerService.java
public InputManagerService(Context context) {
    this(new Injector(context, DisplayThread.get().getLooper()));
}
InputManagerService(Injector injector) {
    ...
    //初始化native层的服务
    mNative = injector.getNativeService(this);
    ...
}
static class Injector {
    NativeInputManagerService getNativeService(InputManagerService service) {
        return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue());
    }
}
NativeInputManagerService.java
class NativeImpl implements NativeInputManagerService {
    NativeImpl(InputManagerService service, MessageQueue messageQueue) {
        mPtr = init(service, messageQueue);
    }
    
    private native long init(InputManagerService service, MessageQueue messageQueue);
}

在初始化JAVA层的InputManagerService时最后会调用到native方法init,进行Native层的输入服务初始化操作,对应的Native层方法是nativeInit

com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj, jobject messageQueueObj) {
    //获取之前就初始化过的native层MessageQueue对象的引用
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    static std::once_flag nativeInitialize;
    NativeInputManager* im = nullptr;
    //call_once方法保证多线程安全,只会执行一次
    std::call_once(nativeInitialize, [&]() {
        im = new NativeInputManager(serviceObj, messageQueue->getLooper());
    });
    LOG_ALWAYS_FATAL_IF(im == nullptr, "NativeInputManager was already initialized.");
    return reinterpret_cast<jlong>(im);
}

NativeInputManager::NativeInputManager(jobject serviceObj, const sp<Looper>& looper)
      : mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();

    mServiceObj = env->NewGlobalRef(serviceObj);

    InputManager* im = new InputManager(this, *this);
    mInputManager = im;
    defaultServiceManager()->addService(String16("inputflinger"), im);
}

nativeInit方法里创建了Native层的输入管理对象NativeInputManager,构造函数里,创建了Java层的InputManagerService对象在native中的全局引用,并创建了InputManager对象:

InputManager.cpp
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,
                           InputDispatcherPolicyInterface& dispatcherPolicy) {
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mProcessor = std::make_unique<InputProcessor>(*mDispatcher);
    mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mProcessor);
    mReader = createInputReader(readerPolicy, *mBlocker);
}

InputManager创建了四个对象:InputDispatcherInputProcessorUnwantedInteractionBlockerInputReader。事件的流动路径为InputReader -> UnwantedInteractionBlocker -> InputProcessor -> InputDispatcher
我们重点关注下InputReaderInputDispatcher。顾名思义,InputReader负责读取输入事件,InputDispatcher负责分发输入事件。

1.1 InputReader

在创建InputReader的同时还会先创建一个EventHub对象。

InputDispatcherFactory.cpp
std::unique_ptr<InputReaderInterface> createInputReader(
        const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {
    return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);
}

EvnetHub监听“/dev/input”这个文件路径,里面的文件名字格式是"eventX", 其中X是从零开始的数字,每个输入设备对应一个event文件,输入事件会被内核的系统写入对应文件中,EventHub就监听这个目录并从中读取事件。

EventHub.cpp
EventHub::EventHub(void)
      : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
        mNextDeviceId(1),
        mControllerNumbers(),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false),
        mNeedToScanDevices(true),
        mPendingEventCount(0),
        mPendingEventIndex(0),
        mPendingINotify(false) {
    ...
    //创建一个epoll实例
    mEpollFd = epoll_create1(EPOLL_CLOEXEC);
    
    //创建用于监听文件变动的文件描述符
    mINotifyFd = inotify_init1(IN_CLOEXEC);
    ...
    //检查系统是否存在"/dev/input"文件夹,如果存在则将该文件路径添加到mINotifyFd实例里进行监听
    if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
        addDeviceInputInotify();
    } else {
        //如果不存在则将"/dev"文件夹路径添加到mINotifyFd实例里进行监听
        addDeviceInotify();
        ...
    }
    ...
    struct epoll_event eventItem = {};
    //监听的事件为有普通数据可读的事件和唤醒事件
    eventItem.events = EPOLLIN | EPOLLWAKEUP;
    eventItem.data.fd = mINotifyFd;
    //向mEpollFd实例添加一个监听特定事件类型的文件描述符mINotifyFd
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    ...
}

1.2 InputDispatcher

InputDispatcher的构造方法里创建了Looper对象,用于后续的无限循环分发事件过程中,起到阻塞、唤醒分发线程的作用。

InputDispatcherFactory.cpp
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy)
      : InputDispatcher(policy, STALE_EVENT_TIMEOUT) {}

InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
                                 std::chrono::nanoseconds staleEventTimeout)
      : ...) {
    mLooper = sp<Looper>::make(false);
    ...
}

2. 输入事件的处理过程

在初始化好Native层的InputManagerService后,我们回到SystemServerstartOtherServices方法中,接着就会继续调用InputManagerServicestart方法,其内部依旧还是调用Native方法start,对应到Native层是com_android_server_input_InputManagerService.cpp中的nativeStart方法:

com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);

    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

接着看InputManagerstart方法,里面依次调用InputDispatcherInputReaderstart方法:

InputManager.cpp
status_t InputManager::start() {
    status_t result = mDispatcher->start();
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReader->start();
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);

        mDispatcher->stop();
        return result;
    }

    return OK;
}

2.1 InputDispatcher的start

InputDispatcherstart里创建了一个名为"InputDispatcher"的线程,这个线程在创建时就会调用dispatchOnce这个方法。

InputDispatcher.cpp
status_t InputDispatcher::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}

InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
    //计算下次唤醒时间
    nsecs_t nextWakeupTime = LLONG_MAX;
    ...
    mLooper->pollOnce(timeoutMillis);
}

dispatchOnce里会调用LooperpollOnce方法,这个方法挺重要的,经常能在涉及到消息机制的代码里见到,最后走到的是pollInner方法,内部使用了epoll_wait方式进行阻塞式等待事件的写入或超时唤醒:

Loooper.cpp
int Looper::pollInner(int timeoutMillis) {
    ...
    //一次最大读取事件数量为16
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    //mEpollFd:被监听的文件描述符;timeoutMillis:超时时间,-1则无限阻塞等待,0则立即返回
    int eventCount = epoll_wait(mEpollFd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    //后续会将这些事件交给MessageHandler的handlerMessage里处理
    ...
}

2.2 InputReader的事件读取

我们接着看InputReaderstart方法,创建了一个名称为"InputReader"的线程,并开始不停循环执行了loopOnce方法。

InputReader.cpp
status_t InputReader::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
    return OK;
}

void InputReader::loopOnce() {
    ...
    //从EventHub中读取事件
    std::vector<RawEvent> events = mEventHub->getEvent(timeoutMillies);
    ...
    //逐级向上传递输入事件
    notifyAll(std::move(notifyArgs));
    ...
}

void InputReader::notifyAll(std::list<NotifyArgs>&& argsList) {
    for (const NotifyArgs& args : argsList) {
        mQueuedListener.notify(args);
    }
}
InputListener.cpp
void InputListenerInterface::notify(const NotifyArgs& generalArgs) {
    Visitor v{
            [&](const NotifyInputDevicesChangedArgs& args) { notifyInputDevicesChanged(args); },
            [&](const NotifyConfigurationChangedArgs& args) { notifyConfigurationChanged(args); },
            [&](const NotifyKeyArgs& args) { notifyKey(args); },
            [&](const NotifyMotionArgs& args) { notifyMotion(args); },
            [&](const NotifySwitchArgs& args) { notifySwitch(args); },
            [&](const NotifySensorArgs& args) { notifySensor(args); },
            [&](const NotifyVibratorStateArgs& args) { notifyVibratorState(args); },
            [&](const NotifyDeviceResetArgs& args) { notifyDeviceReset(args); },
            [&](const NotifyPointerCaptureChangedArgs& args) { notifyPointerCaptureChanged(args); },
    };
    std::visit(v, generalArgs);
}

这些类使用了装饰者模式,notify的调用链路:InputReader -> UnwantedInteractionBlocker -> InputProcess -> InputDispatcher。notify方法根据传进去的args参数类型调用对应的notify方法,假设我们本次接收到的是触屏事件MotionEvent,则最后走到了InputDispatchernotifyMotion方法。

2.3 InputDispatcher的唤醒

InputDispatcher.cpp
void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
    ...
    bool needWake = false;
    {
        mLock.lock();
        //创建MotionEntry实例
        std::unique_ptr<MotionEntry> newEntry =
                    std::make_unique<MotionEntry>(args.id, args.eventTime, args.deviceId, args.source,
                                                  args.displayId, policyFlags, args.action,
                                                  args.actionButton, args.flags, args.metaState,
                                                  args.buttonState, args.classification, args.edgeFlags,
                                                  args.xPrecision, args.yPrecision,
                                                  args.xCursorPosition, args.yCursorPosition,
                                                  args.downTime, args.pointerCount,
                                                  args.pointerProperties, args.pointerCoords);
        //将MotionEvent插入mInboundQueue队列
        needWake = enqueueInboundEventLocked(std::move(newEntry));
        mLock.unlock();
    }
    //唤醒looper对象
    if(needWake) {
        mLooper->wake();
    }
}

InputDispatcher会先创建MotionEvent对象并插入mInboundQueue队列,enqueueInboundEventLocked里会判断是否有目标窗口,有的话就会唤醒mLooper对象,这时我们就需要回到前面说到的dispatchOnce方法里的mLooper->pollOnce这里,开启下一轮dispatchOnce的执行:

InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
    ...
    {
        ...
        //如果没有优先处理的command,就正常执行事件的分发
        if (!haveCommandsLocked()) {
            dispatchOnceInnerLocked(&nextWakeupTime);
        }
        ...
    }
    mLooper->pollOnce(timeoutMillis);
}


void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    ...
    if (!mPendingEvent) {
        if (mInboundQueue.empty()) {
            ...
        } else {
            //从mInboundQueue中取出事件
            mPendingEvent = mInboundQueue.front();
            mInboundQueue.pop_front();
            ...
        }
        ...
    }
    switch (mPendingEvent->type) {
        ...
        case EventEntry::Type::MOTION: {
            ...
            done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
            break;
        }
        ...
    }
    ...
}

InputDispatcher处理两种事件类型,一个是Command,一个是EventEntry,优先执行前者,其次后者。
在处理后者时会先判断当前是否将mInboundQueue中取出MotionEvent,并将其赋给mPendingEvent,并调用dispatchMotionLocked方法:

bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,
                                           DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ...
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
                                          std::shared_ptr<EventEntry> eventEntry,
                                          const std::vector<InputTarget>& inputTargets) {
    ...
    for (const InputTarget& inputTarget : inputTargets) {
        ...
        prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
        ...
    }
}

void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
                                                 const std::shared_ptr<Connection>& connection,
                                                 std::shared_ptr<EventEntry> eventEntry,
                                                 const InputTarget& inputTarget) {
    ...
    //如果处于分屏,另做处理
    if (inputTarget.flags.test(InputTarget::Flags::SPLIT)) {
        ...
        return l
    }
    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}

void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
                                                   const std::shared_ptr<Connection>& connection,
                                                   std::shared_ptr<EventEntry> eventEntry,
                                                   const InputTarget& inputTarget) {
    ...
    const bool wasEmpty = connection->outboundQueue.empty();

    // 根据目标窗口的flags,对应将输入事件封装成DispatchEntry
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::Flags::DISPATCH_AS_HOVER_EXIT);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::Flags::DISPATCH_AS_OUTSIDE);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::Flags::DISPATCH_AS_HOVER_ENTER);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::Flags::DISPATCH_AS_IS);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT);
    enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
                               InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER);

    if (wasEmpty && !connection->outboundQueue.empty()) {
        startDispatchCycleLocked(currentTime, connection);
    }
}

InputDispatcher会在enqueueDispatchEntryLocked中根据目标窗口的flags将EventEntry封装成DispatchEntry,并将其插入outboundQueue中。然后当之前的outboundQueue为空并之后的outboundQueue不为空即代表目标窗口有这些flag时,进行后续的事件分发。

void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                                               const std::shared_ptr<Connection>& connection) {
    ...
    while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
        ...
        switch (eventEntry.type) {
            ...
            case EventEntry::Type::MOTION: {
                //向客户端发布MotionEvent
                status = publishMotionEvent(*connection, *dispatchEntry);
                break;
            }
            ...
        }
        //清除掉outboundQueue中的事件
        connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
                                                    connection->outboundQueue.end(),
                                                    dispatchEntry));
        //将事件插入waitQueue
        connection->waitQueue.push_back(dispatchEntry);
        //设置超时时间,用于抛出ANR
        if (connection->responsive) {
            mAnrTracker.insert(dispatchEntry->timeoutTime,
                               connection->inputChannel->getConnectionToken());
        }
    }
    ...
}

发布事件给客户端后,会将事件从outboundQueue中取出并插入waitQueue中。我们看看事件是怎么发给客户端进程的,

status_t InputDispatcher::publishMotionEvent(Connection& connection,
                                             DispatchEntry& dispatchEntry) const {
    ...
     return connection.inputPublisher
            .publishMotionEvent(dispatchEntry.seq, dispatchEntry.resolvedEventId,
                                motionEntry.deviceId, motionEntry.source, motionEntry.displayId,
                                std::move(hmac), dispatchEntry.resolvedAction,
                                motionEntry.actionButton, dispatchEntry.resolvedFlags,
                                motionEntry.edgeFlags, motionEntry.metaState,
                                motionEntry.buttonState, motionEntry.classification,
                                dispatchEntry.transform, motionEntry.xPrecision,
                                motionEntry.yPrecision, motionEntry.xCursorPosition,
                                motionEntry.yCursorPosition, dispatchEntry.rawTransform,
                                motionEntry.downTime, motionEntry.eventTime,
                                motionEntry.pointerCount, motionEntry.pointerProperties,
                                usingCoords);
}
InputTransport.cpp
status_t InputPublisher::publishMotionEvent(
        uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId,
        std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
        int32_t edgeFlags, int32_t metaState, int32_t buttonState,
        MotionClassification classification, const ui::Transform& transform, float xPrecision,
        float yPrecision, float xCursorPosition, float yCursorPosition,
        const ui::Transform& rawTransform, nsecs_t downTime, nsecs_t eventTime,
        uint32_t pointerCount, const PointerProperties* pointerProperties,
        const PointerCoords* pointerCoords) {
    ...
    InputMessage msg;
    msg.header.type = InputMessage::Type::MOTION;
    ...
    return mChannel->sendMessage(&msg);
}

status_t InputChannel::sendMessage(const InputMessage* msg) {
    const size_t msgLength = msg->size();
    InputMessage cleanMsg;
    msg->getSanitizedCopy(&cleanMsg);
    ssize_t nWrite;
    do {
        nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
    } while (nWrite == -1 && errno == EINTR);
    ...
    return OK;
}

InputDispatcher调用publishMotionEvent方法进行输入事件的分发,而系统进程和客户端进程之间通信的方式是socketpair。这里调用InputChannelsendMessage方法将输入事件写入服务端的fd,客户端通过socketpair机制就能接收到,下一小节详细介绍是怎么建立通信的。

2.4 InputChannel

InputChannel是一个可序列化类型,指定一个文件描述符,用于将输入事件传给另一个进程的窗口。
由于InputDispatcher属于systemSever进程,而接收并消费事件的属于客户端进程,所以事件的传递属于跨进程操作,InputChannel就是为这两个进程建立起了能够通信的通道,其核心机制就是linux的socketpair机制。

InputChannel的建立要追溯到VIewRootImplsetView方法,这个方法是在ActivityThread执行handleResumeActivity方法即Activityresume生命周期时调用的。

ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
    synchronized (this) {
        ...
        //创建InputChannel
        InputChannel inputChannel = null;
        if ((mWindowAttributes.inputFeatures
                & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
            inputChannel = new InputChannel();
        }
        ...
        //通过Binder机制调用Session的addToDisplayAsUser方法
        res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                getHostVisibility(), mDisplay.getDisplayId(), userId,
                mInsetsController.getRequestedVisibleTypes(), inputChannel, mTempInsets,
                mTempControls, attachedFrame, compatScale);
        //创建WindowInputEventReceiver,接收输入事件
        if (inputChannel != null) {
            if (mInputQueueCallback != null) {
                mInputQueue = new InputQueue();
                mInputQueueCallback.onInputQueueCreated(mInputQueue);
            }
            mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
                    Looper.myLooper());
            ...
        }
        ...
    }
}

正因为InputChannel可序列化的特性,所以才能通过Binder机制将其传给systemServer进程的WMS框架里面。

Session.java
@Override
public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
        int viewVisibility, int displayId, int userId, @InsetsType int requestedVisibleTypes,
        InputChannel outInputChannel, InsetsState outInsetsState,
        InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
        float[] outSizeCompatScale) {
    return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
            requestedVisibleTypes, outInputChannel, outInsetsState, outActiveControls,
            outAttachedFrame, outSizeCompatScale);
}

接着调用WindowManagerServiceaddWindow方法:

WindowManagerService.java
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
            int displayId, int requestUserId, @InsetsType int requestedVisibleTypes,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
            float[] outSizeCompatScale) {
    ...
    final boolean openInputChannels = (outInputChannel != null
            && (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
    if  (openInputChannels) {
        win.openInputChannel(outInputChannel);
    }
    ...
}

WMS为每个窗口创建一个WindowState,并调用其openInputChannel方法,

WindowState.java
void openInputChannel(@NonNull InputChannel outInputChannel) {
    if (mInputChannel != null) {
        throw new IllegalStateException("Window already has an input channel.");
    }
    String name = getName();
    mInputChannel = mWmService.mInputManager.createInputChannel(name);
    mInputChannelToken = mInputChannel.getToken();
    mInputWindowHandle.setToken(mInputChannelToken);
    mWmService.mInputToWindowMap.put(mInputChannelToken, this);
    mInputChannel.copyTo(outInputChannel);
}

InputManagerServicecreateInputChannel方法里,最终是走到了native方法里,进行SystemServer进程里native层InputChannel对象的创建,并调用copy方法里将指向native层InputChannel实例的引用传给客户端持有的InputChannel对象里(依靠aidl方法addToDisplayAsUser中InputChannel参数前面的out修饰词完成赋值到客户端)。我们先看怎么创建native层的InputChannel的:

InputManagerService.java
public InputChannel createInputChannel(String name) {
    return mNative.createInputChannel(name);
}
com_android_server_input_InputManagerService.cpp
base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
        const std::string& name) {
    ATRACE_CALL();
    return mInputManager->getDispatcher().createInputChannel(name);
}

调用InputDispatchercreateInputChannel方法:

InputDispatcher.cpp
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
    std::unique_ptr<InputChannel> serverChannel;
    std::unique_ptr<InputChannel> clientChannel;
    //创建socketpair,用于serverChannel和ClientChannel通信
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
    ...
    { // acquire lock
        std::scoped_lock _l(mLock);
        const sp<IBinder>& token = serverChannel->getConnectionToken();
        int fd = serverChannel->getFd();
        //创建serverChannel的connection
        std::shared_ptr<Connection> connection =
                std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
                                             mIdGenerator);

        ...
        mConnectionsByToken.emplace(token, connection);

        std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                            this, std::placeholders::_1, token);

        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
                       nullptr);
    } // release lock

    // Wake the looper because some connections have changed.
    mLooper->wake();
    return clientChannel;
}

openInputChannelPair里创建了server端的InputChannel和client端的InputChannel,并创建socketpair通信。

InputTransport.cpp
status_t InputChannel::openInputChannelPair(const std::string& name,
                                            std::unique_ptr<InputChannel>& outServerChannel,
                                            std::unique_ptr<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=%s(%d)", name.c_str(),
              strerror(errno), errno);
        outServerChannel.reset();
        outClientChannel.reset();
        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));

    sp<IBinder> token = new BBinder();

    std::string serverChannelName = name + " (server)";
    android::base::unique_fd serverFd(sockets[0]);
    outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);

    std::string clientChannelName = name + " (client)";
    android::base::unique_fd clientFd(sockets[1]);
    outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
    return OK;
}

如上,创建了SystemServer进程里的两个InputChannelserverChannelclientChannel),每个通道都持有一个socketpair的fd。serverChannel会被保存在本地并被包装成一个Connection对象,并将这个通道的fd注册到InputDispatcherLooper监控列表中,这样后续客户端的socket写入数据,Looper就会被唤醒并回调handleReceiveCallback。接着将clientChannel引用通过copy方法传递给客户端的InputChannel里,这样客户端就持有clientChannel的引用了。

我们知道了客户端怎么向服务端通信,那服务端SystemServer是怎么通过socketpair将事件传递给app客户端的呢?
我们回到ViewRootImplsetView方法:

ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
        int userId) {
    ...
    if (inputChannel != null) {
        if (mInputQueueCallback != null) {
            mInputQueue = new InputQueue();
            mInputQueueCallback.onInputQueueCreated(mInputQueue);
        }
        mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
                Looper.myLooper());
        ...
    }
}

这里是在创建InputChannel并调用addToDisplayAsUser之后,接着就创建了WindowInputEventReceiver,负责接收服务端传递过来的事件。
WindowInputEventReceiver继承自抽象类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),
            mInputChannel, mMessageQueue);

    mCloseGuard.open("InputEventReceiver.dispose");
}

nativeInit

android_view_InputEventReceiver.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject inputChannelObj, jobject messageQueueObj) {
    ...
    sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
            receiverWeak, inputChannel, messageQueue);
    status_t status = receiver->initialize();
    ...
    return reinterpret_cast<jlong>(receiver.get());
}

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, nullptr);
        } else {
            mMessageQueue->getLooper()->removeFd(fd);
        }
    }
}

在native层,创建NativeInputEventReceiver来对应Java层的InputEventReceiver,并执行initialize方法完成客户端socket的fd的注册监听,监听的事件类型为ALOOPER_EVENT_INPUT,监听到写入时的回调函数是NativeInputEventReceiverhandleEvent方法。

所以,当之前说过的服务端调用InputChannelsendMessage时,就是将事件写入服务端socket的fd中,此时客户端的Looper就会被唤醒,交给handleEvent这个回调函数处理:

android_view_InputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
    ...
    //监听到的事件就是我们想要的输入事件ALOOPER_EVENT_INPUT
    if (events & ALOOPER_EVENT_INPUT) {
        JNIEnv* env = AndroidRuntime::getJNIEnv();
        status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
        mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
        return status == OK || status == NO_MEMORY ? KEEP_CALLBACK : REMOVE_CALLBACK;
    }
    ...
}

status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    ...
    for (;;) {
        uint32_t seq;
        InputEvent* inputEvent;
        //从fd中取出事件
        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) {
        if (mMsgDeferred) {
            mMsgDeferred = false;
        } else {
            status_t result = mChannel->receiveMessage(&mMsg);
            ...
        }
    }
}

接着调用客户端的InputChannelreceiverMessage方法:

InputTransport.cpp
status_t InputChannel::receiveMessage(InputMessage* msg) {
    ssize_t nRead;
    do {
        nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);
    } while (nRead == -1 && errno == EINTR);
    ...
}

receiverMessage里使用recv函数从客户端socket的fd中取出输入事件,赋值给msg,然后我们回到NativeInputEventReceiverconsumeEvents方法里:

android_view_InputEventReceiver.cpp
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
        bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
    ...
    for (;;) {
        uint32_t seq;
        InputEvent* inputEvent;
        //从fd中取出输入事件
        status_t status = mInputConsumer.consume(&mInputEventFactory,
                consumeBatches, frameTime, &seq, &inputEvent);
        ...
        if (!skipCallbacks) {
            ...
            jobject inputEventObj;
            switch (inputEvent->getType()) {
                ...
                case InputEventType::MOTION: {
                    const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*inputEvent);
                    ...
                    //将native层的MotionEvent转成Java层的MotionEvent对象
                    inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
                    break;
                }
                ...
            }
            if (inputEventObj) {
                //调用JAVA层InputEventReceiver对象的dispatchInputEvent方法
                env->CallVoidMethod(receiverObj.get(),
                        gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
                ...
            } else {
                ...
            }
        }
    }
}

consumeEvents中,会先将native的MotionEvent对象转成java层的MotionEvent对象,并调用Java的InputEventReceiverdispatchInputEvent方法,将输入事件传过去。
这样,我们就走到了Java层,输入事件流程梳理的第一节就先到这里了,下一节看看Java层是怎么处理这个输入事件的。

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值