Android系统输入事件启动
以后我打算换一种写法,前面的文章很多都是大段大段代码往上扔,别说大家了,我想回过头来看的时候都觉得恶心,所以我以后叙述多一些,多说一些原理性的东西,这样让人一看就知道怎么回事。
简介
输入事件是目前我发现第2个使用到socket传输的机制,这部分内容启动过程比较简单,读取过程也比较简单,但是分发机制就比较复杂,因为牵扯到WMS对应的内容,负责要将事件分发到那个窗口,所以我们就由简单到深入了解一下Android中输入事件机制。
首先我们从InputManagerService开始,InputManagerService是输入事件的管理者,就和我们的WMS,ANS,PMS一样起着管理作用。那我们就按照惯例从构造看。
InputManagerService在构造的时候期初创建了几个核心的类:
- InputDispatcher.cpp
- InputReader.cpp
- InputManager.cpp
- EventHub.cpp
- InputListener.cpp
对于InputDispatcher与InputReader来说一个是用于分发事件一个是用来获取事件。所以如果我们需要设计,肯定是两个线程,两个死循环,一个不断读取,一个不断分发。那么Android系统里面是如何做的呢?
系统中用InputManager来管理InputDispatcher与InputReader对应的线程
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
并且InputDispatcher有自己的Looper对象。那InputDispatcher与InputReader是通过什么链接起来的呢?
在InputReader中
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) {
// 创建输入监听对象
mQueuedListener = new QueuedInputListener(listener);
{
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
}
}
其中const sp<InputListenerInterface>& listener
就是将InputDispatcher对象传递到InputReader中然后传到QueuedInputListener里面。
这样就理清楚了,InputManager创建了InputReader,InputDispatcher并且InputReader持有InputDispatcher的引用。
对应工作线程
void InputManager::initialize() {
//创建线程“InputReader”
mReaderThread = new InputReaderThread(mReader);
//创建线程”InputDispatcher“
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
}
这两个国宝级别的线程在InputManagerService.start的时候开始工作
public void start() {
nativeStart(mPtr);
}
在native里面使用的NativeInputManager其中的InputManager进行start
status_t InputManager::start() {
result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
...
return OK;
}
最后终于启动了两个国宝线程
小结启动过程中的相关事情
- 在native中创建了NativeInputManager对象,并且将NativeInputManager对象的指针交到java层的mPtr中保存起来,mPtr存在与IMS中
- 在这个过程中创建了几个核心的类:
- NativeInputManager :native层的管理
- EventHub:将多种格式的消息统一成一种格式给framework使用
- InputManager:用于创建对应的InputReader与InputDispatcher核心的类
- InputReaderThread:对应读取事件的线程
- InputDispatcherThread:对应分发事件的线程
- 在这里面包含了3个线程
- 一开始在framework的DisplayThread:有自己的Looper
- InputReaderThread
- InputDispatcherThread:有自己的Looper