Android开发经验谈Android技术知识Android开发

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

2020-05-11  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读