相关文章连接:java
1. Android Framework - 学习启动篇
2. Android FrameWork - 开机启动 SystemServer 进程linux
相关源码文件:android
/frameworks/base/services/java/com/android/server/SystemServer.java /frameworks/base/services/core/java/com/android/server/input/InputManagerService.java /frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp /frameworks/native/services/inputflinger/InputDispatcher.cpp /frameworks/native/services/inputflinger/InputReader.cpp /frameworks/native/services/inputflinger/InputManager.cpp /frameworks/native/services/inputflinger/EventHub.cpp
对于 Android 上层事件分发的过程,你们应该都是比较熟悉的,由于这是自定义 View 的一个知识点,也是前几年面试常问的一个问题。但只是知道上层的事件分发过程可能还不够,由于不少高级功能开发须要依赖底层的一些知识。咱们应该都知道事件通常会传递到 activity 根布局 view 的 dispatchTouchEvent 方法,那么咱们有没有思考过事件的源头在哪里?这个事件最初究竟是从哪里发出来的?web
这里咱们先梳理作一个总体的总结,手机点击屏幕首先从硬件传递到驱动,咱们以前提到过在 linux 内核系统中一切皆文件,所以咱们只须要监听 /dev/input 驱动文件的变化就能读取到事件;因此在 Android 系统中会有一个 InputReader 专门来负责读取 Input 事件,还有一个 InputDispatcher 专门把读取到的 Input 事件分发出来。面试
/** * Starts a miscellaneous grab bag of stuff that has yet to be refactored * and organized. */ private void startOtherServices() { final Context context = mSystemContext; ... // 建立 InputManagerService InputManagerService inputManager = new InputManagerService(context); // 建立 WindowManagerService wm = WindowManagerService.main(context, inputManager, mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !mFirstBoot, mOnlyCore); // 注册系统服务 ServiceManager.addService(Context.WINDOW_SERVICE, wm); ServiceManager.addService(Context.INPUT_SERVICE, inputManager); // 设置管理的 callback inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start(); } public InputManagerService(Context context) { this.mContext = context; // 建立 InputManagerHandler this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); ... // native 层初始化,这里会用到 handler 的 looper 的底层通讯机制,handler 也是能够跨进程通讯的 mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); } static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { // 拿到 native 层的 MessageQueue 对象 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); if (messageQueue == NULL) { jniThrowRuntimeException(env, "MessageQueue is not initialized."); return 0; } // 建立 native 层的 NativeInputManager NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); return reinterpret_cast<jlong>(im); } NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) : mLooper(looper), mInteractive(true) { ... // 建立 EventHub 与 InputManager sp<EventHub> eventHub = new EventHub(); mInputManager = new InputManager(eventHub, this, this); } InputManager::InputManager( const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) { // 建立 InputDispatcher 与 InputReader mDispatcher = new InputDispatcher(dispatcherPolicy); mReader = new InputReader(eventHub, readerPolicy, mDispatcher); initialize(); } void InputManager::initialize() { // 建立 InputDispatcher 与 InputReader 线程 mReaderThread = new InputReaderThread(mReader); mDispatcherThread = new InputDispatcherThread(mDispatcher); } status_t InputManager::start() { // 分别启动 InputDispatcher 与 InputReader 线程 status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); ... result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); ... return OK; }
IMS 的启动入口在 SystemServer 进程中,InputManagerService 在构建对象的时候会建立 native 层的 NativeInputManager 对象,NativeInputManager 中又会构建 EventHub 与 InputManager 对象,最后 InputManager 会分别建立和启动 InputDispatcher 与 InputReader 线程。windows
EventHub::EventHub(void) : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(), mOpeningDevices(0), mClosingDevices(0), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); // 建立 epoll mEpollFd = epoll_create(EPOLL_SIZE_HINT); mINotifyFd = inotify_init(); // 此处 DEVICE_PATH 为"/dev/input",监听该设备路径,这个代码在驱动层,感兴趣你们本身跟一下 int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE); struct epoll_event eventItem; memset(&eventItem, 0, sizeof(eventItem)); eventItem.events = EPOLLIN; eventItem.data.u32 = EPOLL_ID_INOTIFY; // 添加 INotify 到 epoll 实例 result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem); int wakeFds[2]; result = pipe(wakeFds); // 建立管道 mWakeReadPipeFd = wakeFds[0]; mWakeWritePipeFd = wakeFds[1]; // 将 pipe 的读和写都设置为非阻塞方式 result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); eventItem.data.u32 = EPOLL_ID_WAKE; // 添加管道的读端到 epoll 实例 result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem); ... } InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) : mContext(this), mEventHub(eventHub), mPolicy(policy), mGlobalMetaState(0), mGeneration(1), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), mConfigurationChangesToRefresh(0) { // 建立输入监听对象 QueuedInputListener 就是 InputDispatcher mQueuedListener = new QueuedInputListener(listener); ... } void InputReader::loopOnce() { int32_t oldGeneration; int32_t timeoutMillis; ... // 从 mEventHub 中获取 Events 事件 ,EVENT_BUFFER_SIZE = 256 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); { // acquire lock AutoMutex _l(mLock); mReaderIsAliveCondition.broadcast(); // 处理事件 if (count) { processEventsLocked(mEventBuffer, count); } ... } // release lock // 发送事件到 InputDispatcher mQueuedListener->flush(); } size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { struct input_event readBuffer[bufferSize]; // 原始事件 RawEvent* event = buffer; // 容量大小 size_t capacity = bufferSize; for (;;) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); ... if (mNeedToScanDevices) { mNeedToScanDevices = false; // 扫描设备 scanDevicesLocked(); mNeedToSendFinishedDeviceScan = true; } // Grab the next input event. bool deviceChanged = false; while (mPendingEventIndex < mPendingEventCount) { const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++]; // 从设备不断读取事件,放入到 readBuffer // 获取 readBuffer 的数据, 将 input_event 信息, 封装成 RawEvent } // 等待input事件的到来 int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis); } // 返回所读取的事件个数 return event - buffer; } void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) { for (const RawEvent* rawEvent = rawEvents; count;) { int32_t type = rawEvent->type; size_t batchSize = 1; if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) { int32_t deviceId = rawEvent->deviceId; while (batchSize < count) { if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT || rawEvent[batchSize].deviceId != deviceId) { break; } batchSize += 1; } // 真正分发事件 processEventsForDeviceLocked(deviceId, rawEvent, batchSize); } else { // 添加设备类型有:获取键盘源类型,键盘类设备类型, 鼠标类设备类型,触摸屏设备类型 switch (rawEvent->type) { case EventHubInterface::DEVICE_ADDED: addDeviceLocked(rawEvent->when, rawEvent->deviceId); break; ... } } count -= batchSize; rawEvent += batchSize; } } void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count) { // 这里主要分析触摸事件 ssize_t deviceIndex = mDevices.indexOfKey(deviceId); InputDevice* device = mDevices.valueAt(deviceIndex); device->process(rawEvents, count); } void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source, int32_t action, int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags, const PointerProperties* properties, const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) { ... // 封装成 NotifyMotionArgs 通知给 InputDispatcher NotifyMotionArgs args(when, getDeviceId(), source, policyFlags, action, actionButton, flags, metaState, buttonState, edgeFlags, mViewport.displayId, pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime); getListener()->notifyMotion(&args); }
InputReader 线程启动后会不断的经过 EventHub 去读取事件信息,而后再把事件信息解析封装成不一样的对象,最后再经过回掉的方式通知 InputDispatcher 。其中添加设备类型有:键盘类设备类型, 鼠标类设备类型,触摸屏设备类型等。app
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) : mPolicy(policy), mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX), mNextUnblockedEvent(NULL), mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false), mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) { // 建立 Looper 对象 mLooper = new Looper(false); // 获取分发超时参数 policy->getDispatcherConfiguration(&mConfig); } void InputDispatcher::dispatchOnce() { nsecs_t nextWakeupTime = LONG_LONG_MAX; { AutoMutex _l(mLock); // 唤醒等待线程,monitor() 用于监控 dispatcher 是否发生死锁 mDispatcherIsAliveCondition.broadcast(); if (!haveCommandsLocked()) { // 当 mCommandQueue 不为空时处理 dispatchOnceInnerLocked(&nextWakeupTime); } if (runCommandsLockedInterruptible()) { nextWakeupTime = LONG_LONG_MIN; } } nsecs_t currentTime = now(); int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime); // 进入等待,须要调用 mLooper.wake 方法来唤醒 mLooper->pollOnce(timeoutMillis); } void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { ... if (! mPendingEvent) { if (mInboundQueue.isEmpty()) { // Nothing to do if there is no pending event. if (!mPendingEvent) { // 没有事件须要处理直接返回 return; } } else { // Inbound queue has at least one entry. mPendingEvent = mInboundQueue.dequeueAtHead(); traceInboundQueueLengthLocked(); } } switch (mPendingEvent->type) { ... case EventEntry::TYPE_KEY: { ... // 分发 key 事件 done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime); break; } case EventEntry::TYPE_MOTION: { // 分发触摸事件 done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime); break; } } ... } bool InputDispatcher::dispatchMotionLocked( nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) { ... if (isPointerEvent) { // Pointer event. (eg. touchscreen) injectionResult = findTouchedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime, &conflictingPointerActions); } else { // Non touch event. (eg. trackball) injectionResult = findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime); } if (injectionResult == INPUT_EVENT_INJECTION_PENDING) { return false; } // 最后开始分发 dispatchEventLocked(currentTime, entry, inputTargets); return true; } int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) { if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) { // 遍历全部的 mWindowHandles size_t numWindows = mWindowHandles.size(); for (size_t i = 0; i < numWindows; i++) { sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i); const InputWindowInfo* windowInfo = windowHandle->getInfo(); if (windowInfo->displayId != displayId) { continue; // wrong display } int32_t flags = windowInfo->layoutParamsFlags; if (windowInfo->visible) { // 可见,而且 flags 属性不是 InputWindowInfo::FLAG_NOT_TOUCHABLE if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) { isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0; // 点击的是否是当前 window 的覆盖 if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) { // found touched window, exit window loop // 找到了当前触摸的 window newTouchedWindowHandle = windowHandle; break; } } } } mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds); } else { ... } // 再把 mTempTouchState 收集到的 windows 添加到 inputTargets 中 for (size_t i = 0; i < mTempTouchState.windows.size(); i++) { const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i); addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags, touchedWindow.pointerIds, inputTargets); } ... return injectionResult; } void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) { for (size_t i = 0; i < inputTargets.size(); i++) { const InputTarget& inputTarget = inputTargets.itemAt(i); // 根据 inputChannel 的 fd 从 mConnectionsByFd 队列中查询目标 connection. ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel); if (connectionIndex >= 0) { // 找到目标链接 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex); // 准备分发事件出去了 prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget); } else { ... } } } void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) { bool wasEmpty = connection->outboundQueue.isEmpty(); // Enqueue dispatch entries for the requested modes. enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_OUTSIDE); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_IS); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT); enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER); // If the outbound queue was previously empty, start the dispatch cycle going. if (wasEmpty && !connection->outboundQueue.isEmpty()) { startDispatchCycleLocked(currentTime, connection); } } void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection) { while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.isEmpty()) { ... switch (eventEntry->type) { case EventEntry::TYPE_KEY: { ... break; } case EventEntry::TYPE_MOTION: { MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry); ... // 经过 connection 的 inputPublisher 发布出去了 // Publish the motion event. status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId, motionEntry->source, dispatchEntry->resolvedAction, motionEntry->actionButton, dispatchEntry->resolvedFlags, motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState, xOffset, yOffset, motionEntry->xPrecision, motionEntry->yPrecision, motionEntry->downTime, motionEntry->eventTime, motionEntry->pointerCount, motionEntry->pointerProperties, usingCoords); break; } ... } }
InputDispatcher 采用的是 Looper 的唤醒与等待,这个跟以前分析 Handler 的底层原理是同样的。收到事件后首先会找到分发的目标窗口信息,而后经过 inputTarget 的 inputChannel 找到通讯链接,最后再把事件经过 connection 发布出来,至于发到哪里去了?咱们须要熟悉后面的 WindowManagerService 的源码。svg
视频地址:https://pan.baidu.com/s/1vY_Vb3AaIB9UUWJdPMLOQQ
视频密码:566qoop