美文网首页Android开发经验谈Android技术知识Android开发
Android 系统服务 - Input 事件的分发过程

Android 系统服务 - Input 事件的分发过程

作者: 你也不知道 | 来源:发表于2020-05-11 12:39 被阅读0次

    相关文章链接:

    1. Android Framework - 学习启动篇

    2. Android FrameWork - 开机启动 SystemServer 进程

    相关源码文件:

    
    /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
    
    

    1. 梳理概述

    对于 Android 上层事件分发的过程,大家应该都是比较熟悉的,因为这是自定义 View 的一个知识点,也是前几年面试常问的一个问题。但只是知道上层的事件分发过程可能还不够,因为很多高级功能开发需要依赖底层的一些知识。我们应该都知道事件一般会传递到 activity 根布局 view 的 dispatchTouchEvent 方法,那么我们有没有思考过事件的源头在哪里?这个事件最初到底是从哪里发出来的?

    这里我们先梳理做一个整体的总结,手机点击屏幕首先从硬件传递到驱动,我们之前提到过在 linux 内核系统中一切皆文件,因此我们只需要监听 /dev/input 驱动文件的变化就能读取到事件;所以在 Android 系统中会有一个 InputReader 专门来负责读取 Input 事件,还有一个 InputDispatcher 专门把读取到的 Input 事件分发出来。

    2. IMS 的启动过程

    
      /**
    
      * 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 线程。

    2. Input 事件读取

    
      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 。其中添加设备类型有:键盘类设备类型, 鼠标类设备类型,触摸屏设备类型等。

    3. Input 事件分发

    
      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 的源码。

    视频地址:https://pan.baidu.com/s/1vY_Vb3AaIB9UUWJdPMLOQQ

    视频密码:566q

    相关文章

      网友评论

        本文标题:Android 系统服务 - Input 事件的分发过程

        本文链接:https://www.haomeiwen.com/subject/njcunhtx.html