Android输入系统

Android输入事件分发

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

InputDispatcherThread::~InputDispatcherThread() {
}bool InputDispatcherThread::threadLoop() {mDispatcher->dispatchOnce();return true;
}void InputDispatcher::dispatchOnce() {{ // acquire lockif (!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封装成DispatchEntryDispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments refinputTargetFlags, 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. 爱踢门之锤子自由截屏快捷键配置(下)

    快捷键实现 其实说到这,大家估计都不容易了,这么长的代码,同时也会提出质疑"说好的截屏快捷键配置"呢?怎么都没有提及到啊?其实是有提及到的,就是上面的mPolicy-> in ...

  2. 爱踢门之锤子系统区域截屏功能

    周围有位罗总的忠实粉丝,于是乎平时有意无意的被灌注了大量"锤子"的信息.也许就是这些无意,我昨晚也就无意中点进了锤子手机发布会的直播,看着看着最后就看完了. 锤子的硬件设计是超出期 ...

  3. android qq截屏快捷键是什么,手机截屏的快捷键是什么,超过3种截图的快捷键操作方法!...

    为了方便大家操作,我在这里汇总一些经常被用到的一些截屏快捷键,让大家随时随地都能快捷方便的截图. 1.Windows自身的截屏快捷键 全屏截图:按下键盘上PrtScSysRq这个按键.按了之后你会发现 ...

  4. windows 截屏快捷键x220_笔记本截屏的快捷键是什么_笔记本截屏快捷键是什么

    笔记本截屏的快捷键是什么? 493x220 - 17KB - JPEG 华硕笔记本截屏快捷键失灵怎么使用键盘截屏? 500x451 - 34KB - JPEG 笔记本电脑怎么截屏 笔记本电脑截屏快捷方 ...

  5. QQ浏览器如何修改截屏快捷键?QQ浏览器修改截屏快捷键的方法

    qq浏览器是一款非常好用的搜索服务软件,在日常生活中如果碰到有什么不懂的内容,都可以使用这款软件解决,使用非常的方便,随时都可以满足用户的搜索需求,用户在使用这款软件的时候可以使用到非常多的功能,随时 ...

  6. 快捷键截屏_Windows10自带截屏快捷键使用方法大全

    我们知道,QQ和微信以及第三方浏览器等软件都支持截图功能,但是这个都是基于软件的一个功能,如果我们不打开这些软件的话,就不能实现截图功能,但其实windows10自带的截屏功能十分方便,只是很多人不知 ...

  7. 苹果截屏快捷键_MacOS截屏的那些事儿

    在使用Mac的时候,很多场景下我们都需要使用到截屏.不得不说,在MacOS中进行截屏是一件相当轻松的事情,因为MacOS原生的截屏功能就已经非常好用,完全不需要第三方软件.对比隔壁的Windows,那 ...

  8. mac录屏快捷键 - mac截图截屏快捷键 - 自带录屏软件QuickTime Player如何使用

    mac截图截屏快捷键 全屏截图 command + shift + 3 (截图文件自动保存到桌面) 区域截图 command + shift + 4  再用鼠标框选截图范围(截图文件自动保存到桌面) ...

  9. Ctrl + Alt + A ,唯一的截屏快捷键?

    NO,QQ截屏快捷键 Ctrl + Alt + A 固然方便,但总有要截屏却没登QQ的尴尬.那为什么不考虑win10自带的截屏呢?不方便吗?不不不,只是你还没设置好而已.上车! 首先:自带的截屏快捷键 ...

最新文章

  1. 如何扩容单台服务器的存储容量?
  2. IO流(六)之CharArrayReader类与CharArrayWriter类
  3. njx如何实现负载均衡_负载均衡是怎么做的~
  4. Android ADB
  5. Stateflow变量范围
  6. Ubuntu硬盘安装
  7. Python3.x学习资料汇总(待续)
  8. 谈谈javascript中原型继承
  9. P1165 日志分析 洛谷
  10. virtual studio 2017 配置vistual assist激活
  11. java读CSV文件入数组
  12. redis可视化客户端工具TreeNMS
  13. Android 学习资料收集
  14. 智慧书-永恒的处世经典格言:121-160
  15. python mysql跨库查询_Python查询mysql库
  16. Linux系统时间校准
  17. png的格式及像素存储分析
  18. S3C2440 GPIO控制器
  19. 3DCAT云流送技术如何搅动各大行业
  20. 先少谈点人工智能好吗?

热门文章

  1. uniapp h5公众号授权登录基本流程
  2. o-1背包问题迭代_经典动态规划:01背包问题的变体
  3. 使用PostGIS对数据做拓扑抽稀
  4. oracle数据库添加表空间
  5. VS Code 扩展 WebTS 早期预览版发布;微软开源其搜索服务的 SPTAG 算法
  6. Unity(四十二):EPPlus读写Excel数据、JSON解析
  7. selectkey、插入成功返回主键
  8. eBPF/Ftrace 双剑合璧:no space left on device 无处遁形
  9. Judy 分享——区块链的终极猜想
  10. 利用C语言编写一个网络分析器