Android输入系统

Android输入事件分发

上一篇已经分析完linux事件到android事件的转化,事件已经在队列上,下面就是读取数据并分发了,整个过程如下:


InputDispatcherThread::~InputDispatcherThread() {}bool InputDispatcherThread::threadLoop() {    mDispatcher->dispatchOnce();    return true;}void InputDispatcher::dispatchOnce() {    { // acquire lock        if (!haveCommandsLocked()) {            //分发事件            dispatchOnceInnerLocked(&nextWakeupTime);        }    } // release lock    //等待事件    mLooper->pollOnce(timeoutMillis);}void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {if (! mPendingEvent) {    //从队列中读取下一个事件        mPendingEvent = mInboundQueue.dequeueAtHead();    }    switch (mPendingEvent->type) {    //只分析key事件    case EventEntry::TYPE_KEY: {        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);        break;    }    }}bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,        DropReason* dropReason, nsecs_t* nextWakeupTime) {    // 这个逻辑很重要,是我们实现快捷键动态配置的关键逻辑    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {            // doInterceptKeyBeforeDispatchingLockedInterruptible很重要            CommandEntry* commandEntry = postCommandLocked(                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);            if (mFocusedWindowHandle != NULL) {                commandEntry->inputWindowHandle = mFocusedWindowHandle;            }            commandEntry->keyEntry = entry;            entry->refCount += 1;            return false; // wait for the command to run        } else {            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;        }    }    Vector<InputTarget> inputTargets;    //只有focused window对象才能接收key事件,这也是为什么android系统,按back,menu    //只是当前最top的程序响应的原因    int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,            entry, inputTargets, nextWakeupTime);    if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {        return false;    }    //monitor对象会接收所有key事件    addMonitoringTargetsLocked(inputTargets);    // 真正将key分发给应用,这里的inputTargets就是应用程序的window在native input    //对应的对象    dispatchEventLocked(currentTime, entry, inputTargets);    return true;}void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(        CommandEntry* commandEntry) {    // interceptKeyBeforeDispatching给了java层一个机会去提前处理事件    //由于有返回值,则同时可以达到丢弃该事件的效果,因此该函数也可以很好的    //用来实现快捷键的动态配置    delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,             &event, entry->policyFlags);    mLock.lock();    if (delay < 0) {    //丢弃该事件        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;    } else if (!delay) {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;    } else {        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;        entry->interceptKeyWakeupTime = now() + delay;    }    entry->release();}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);        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);        if (connectionIndex >= 0) {            //我们知道,这里的代码运行在系统进程(system_server),而应用程序运行在            //的进程中,要传递按键信息肯定需要有跨进程的消息传递机制,下面的            //connection就是为了传递输入事件而建立的一个跨进程传递信息的一个对象            //它的具体实现将在后面的章节详细讲解            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);        } else {        }    }}void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {    enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);}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::enqueueDispatchEntryLocked(        const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,        int32_t dispatchMode) {    //将EventEntry封装成DispatchEntry    DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref            inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,            inputTarget->scaleFactor);    // 将事件添加到window的connection的事件队列里    connection->outboundQueue.enqueueAtTail(dispatchEntry);}

到此为止,system层对事件的处理都完成了。总的说来就是system 从linux设备读取事件,然后翻译成android的事件,然后找到事件的对象(获取到焦点的程序),并将此事件放到window对象的connection队列上。大家很容易想到,程序端获取事件的大致流程肯定是:Connection在程序端的代理读取connection server端队列中的事件,并将事件发送到事件处理逻辑。

Connection的建立和数据发送及程序端的事件处理会在后面的章节里详细讲解。


/********************************

* 本文来自博客 “爱踢门”

* 转载请标明出处:http://blog.csdn.net/itleaks

******************************************/

更多相关文章

  1. 类和 Json对象
  2. Service与Android系统实现(1)-- 应用程序里的Service
  3. Android事件处理的两种模型
  4. Android(安卓)中文 API (102)―― CursorAdapter
  5. Android消息机制分析
  6. Android(安卓)Keyboard/Touch Panel分析
  7. Android(安卓)监听软键盘弹起和收起事件
  8. android 按键
  9. Android事件处理第一节(View对Touch事件的处理)

随机推荐

  1. 安卓开发中开关按钮ToggleButton和开关Sw
  2. Android类加载器以及与Java类加载器区别
  3. Android 动画框架详解
  4. 设置Activity大小不再全屏原理
  5. Android(安卓)IntentService的使用与源码
  6. android面试一些常见的问题
  7. Android系统集成第三方pre-build库和程序
  8. android sip协议通话实现
  9. Android系统学习总结1--init和Zygote
  10. 8.16 提炼参数对象