b) processEventsForDeviceLocked从InputReader 的(InputDevice类型)变量mDevices变量中找出当前对应的device,调用其process
c) process调用InputDevice的变量(InputMapper类型)mMappers的process函数
d)这里的mapper是KeyboardInputMapper类
这里process开始调用eventhub类的mapKey()启动参数rawEvent中的linux键值scanCode的转换,变为android键值keyCode,继续调用processKey上传.
e) processKey调用 getListener()->notifyKey(&args); 完成键值上报到其他模块
注意这里的getListener就是取得inputreader类初始化时用参数“const sp
到这里,inputread.cpp模块的按键分发上报全部完成,后续只要搞清楚
sp
4)阐述按键分发中的关键衔接一环:
上述C)步的mMappers是如何和KeyboardInputMapper关联的? 为什么KeyboardInputMapper的getListener()是inputreader的mQueuedListener?
仍然是从loopOnce 调用processEventsLocked开始:
a) processEventsLocked找不到按键rawEvents的设备来源时调用addDeviceLocked:
b) addDeviceLocked调用createDeviceLocked:
(所以上面第3)点钟的B)步能找到有效的device) c) createDeviceLocked调用device->addMapper
到这里就完成了inputreadr----inputdevice---mappers的关联.
getListener的来源:
InputReader构造函数用参数sp
mContext也是InputReader对象的成员,其类型是InputReader的内部类ContextImpl,该类继承自InputReaderContext,ContextImpl的getListener函数直接返回mQueuedListener。
createDeviceLocked在 添加inputdevice设备时,使用mContext转换为InputReaderContext作为参数创建了device,直接赋值给inpudevice的成员变量mContext。
createDeviceLocked继续addMapper创建了KeyboardInputMapper实例,即(new KeyboardInputMapper(device, keyboardSource, keyboardType)); device用于创建InputMapper对象,device的mContext成员赋值给InputMapper的mContext;KeyboardInputMapper又继承自InputMapper。
所以KeyboardInputMapper的成员mContext等价于InputReader的mContext;getListener等价于调用InputReader的mContext->getListener即mQueuedListener。 5)InputReaderThread线程类
构造函数InputReaderThread使用InputReader 类对象作为参数,赋值给变量mReader。
threadLoop方法中调用mReader->loopOnce();
只要创建了InputReader实例,并以此启动InputReaderThread线程,就会反复mEventHub->getEvents读键和调用processEventsLocked分发上报。
3.2.2\\frameworks\\base\\services\\input\\InputDispatcher.cpp
该文件是真正的按键数据上报的起点,InputReader中的listener实际就是这个InputDispatcher,该类继承自接口InputDispatcherInterface。 完成3个事情:
interceptKeyBeforeQueueing,按键入列前的截获处理
interceptKeyBeforeDispatching,按键从队列分发上层app前的截获处理 startDispatchCycleLocked,完成按键最终分发上报 1)InputDispatcher类
a)构造函数以参数policy直接初始化成员变量mpolicy。
b) notifyKey函数被之前的inputreader调用,notifyKey调用interceptKeyBeforeQueueing
进行第一次按键上报,供上层截获按键,在按键被压入队列前进行必要的处理,如设置,桌面等在keyfuntion.xml中配置的快捷键,或待机键等的处理。
到这里完成按键进入Queue队列前的上报处理,如果interceptKeyBeforeQueueing没有处理这个按键,将会继续调用步骤c)。
c) enqueueInboundEventLocked将按键结构参数entry压入队列
d) InputDispatcherThread线程类不断循环,检测到队列中的按键 InputDispatcherThread调用InputDispatcher的dispatchOnce。
e) dispatchOnce调用dispatchOnceInnerLocked
f) dispatchOnceInnerLocked调用dispatchKeyLocked
g) dispatchKeyLocked调用
doInterceptKeyBeforeDispatchingLockedInterruptible
h) doInterceptKeyBeforeDispatchingLockedInterruptible调用 mPolicy->interceptKeyBeforeDispatching
到这里完成进入队列的按键在上报app前的截获处理,比如特殊处理home键,添加工装菜单的按键调用等,如果这些按键仍然没被截获,将继续进行分发,继续下面的步骤i). i) dispatchKeyLocked调用addMonitoringTargetsLocked,获取所有上层注册过需要按键的channel,创建目标通道集合inputTargets; 继续调用dispatchEventLocked开始按键分发。
j) dispatchEventLocked对每一个通道获取其connection,再调用prepareDispatchCycleLocked
k) prepareDispatchCycleLocked调用enqueueDispatchEntriesLocked l) enqueueDispatchEntriesLocked调用enqueueDispatchEntryLocked把按键eventEntry和目标通道inputTarget写入connection 再调用startDispatchCycleLocked开始分发
m) startDispatchCycleLocked调用connection->inputPublisher.publishKeyEvent完成最终分发按键。