Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
来源:互联网 发布:大麦网抢票软件个人版 编辑:程序博客网 时间:2024/03/29 01:29
Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
1. 回顾
我们知道Android输入系统是Reader线程通过驱动程序得到上报的输入事件,还要经过处理,才可以将输入事件发送给应用程序,现在回顾一下是具体做哪些处理。
首先Reader线程会将输入事件放入mInboundQueue队列当中,但是放入队列之前需要进行稍加处理。
1.1 处理类型
- 紧急事件,马上处理(来电振铃时,按下音量键,会马上静音)
- 对输入事件添加Flag,决定输入事件是否传给用户Dispatch线程从mInboundQueue中取出事件,稍加处理之后,查找到目标的应用程序后,便会放入某个应用程序的输出队列(mOutBoundQueue)
从输出队列中将事件取出,发送给应用程序
2. Dispatch前处理总体分析
2.1 命令队列为空时时候
- 从mIboundQueue取出事件
- 用它来生成一个命令,放入命令队列或者直接丢弃(对于!Pass_To_User的事件)
- 对于经过处理的事件,dispatch它
- 对于Global Key丢弃
- System Key 丢弃
- User Key 找到target,dispatch
InputDispatch.cpp
if (!haveCommandsLocked()) { dispatchOnceInnerLocked(&nextWakeupTime);}
2.2 命令队列有数据,执行命令
- Global Key 发广播
- System Key 直接处理
- User Key 不做处理
InputDispatch.cpp
if (runCommandsLockedInterruptible()) { nextWakeupTime = LONG_LONG_MIN;}
3. dispatch前处理情景分析
3.1 !Pass_To_User
- 当policyFlags = !Pass_To_User,则会执行dispatchOnceInnerLocked函数,设置dropreason
DropReason dropReason = DROP_REASON_NOT_DROPPED;if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) { dropReason = DROP_REASON_POLICY;} else if (!mDispatchEnabled) { dropReason = DROP_REASON_DISABLED;}
- 假设是一个按键类型的输入事件,便会调用dispatchKeyLocked处理
// Clean up if dropping the event.if (*dropReason != DROP_REASON_NOT_DROPPED) { setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED); return true;}
3.2 Pass_To_User
- 需要分为Global Key/System Key/User Key三种情况,但是都是首先放入命令队列中,并执行命令,执行的命令根据各个按键的返回值决定。
- 放入命令队列
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { 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
- 执行命令
if (runCommandsLockedInterruptible()) { nextWakeupTime = LONG_LONG_MIN;}
CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();Command command = commandEntry->command;(this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'//command执行doInterceptKeyBeforeDispatchingLockedInterruptible函数
//最终调用PhoneWindowManager.java里面的同名函数nsecs_t 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;}
处理全局按键(Global Key)的代码,返回-1,根据Global_Key.xml发送广播给某个主键
if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {return -1;}
- System Key:直接处理,return -1,意味着不会上传给APP
User Key:return 0,事件解析结果是continue,让APP来处理。再次执行dispatchOnceInnerLocked,最终会找到目标应用程序,然后将该事件发给应用程序
// Identify targets.Vector<InputTarget> inputTargets;int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,entry, inputTargets, nextWakeupTime);
// Dispatch the key.dispatchEventLocked(currentTime, entry, inputTargets);
4. 总结
本篇博文主要分析dispatc前的处理过程,如下图所示:
- 对于Reader线程读到的输入事件,会先进行解析,解析之后进行过滤,如果可以过滤就释放,就不会放入mInBoundQueue队列当中,不可以过滤的话,无论是否Pass_To_User,都会放入mInBoundQueue队列当中
- 从mInBoundQueue队列当中取出输入事件,判断是否Pass_To_User,如果不是Pass_To_User则释放掉,否则放入mCommandQueue当中
- 再从mCommandQueue队列当中,再次做解析,解析之后如果决定可以把他丢弃掉的话就直接release掉,否则则是放在mOutBoundQueue队列中去,APP取出使用。下篇博文会具体分析这一步。
阅读全文
0 0
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
- Android系统--输入系统(十七)Dispatcher线程_分发dispatch
- Android系统--输入系统(十七)Dispatcher线程_分发dispatch
- Android系统源代码情景分析
- Android系统源代码情景分析
- android hardware 简述(Android系统源码情景分析 笔记)
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析之基础知识
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析:基础知识 .
- Android系统源代码情景分析:基础知识 .
- Android系统源代码情景分析:基础知识
- Android系统源代码情景分析:基础知识
- 选择你的Docker管理工具:Kubernetes或Swarm
- iOS PHCollectionList详解
- Glassfish不同WEB项目调用ejb对象
- jQuery Ajax 实例 ($.ajax、$.post、$.get)
- 盗梦空间
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
- Cause: java.sql.SQLException: ORA-01841: (完整) 年份值必须介于 -4713 和 +9999 之间, 且不为 0
- 已解决:HorizontalScrollView的setScrollViewListener方法不兼容低版本的问题
- 1022. D进制的A+B (20)
- 块级元素和行内元素的区别
- mongo find 详解
- MarkDowm常用语法
- 16CF1-B
- 编程笔试题