InputManagerService的创建过程
由SystemServer启动并将其注册到系统服务中。
frameworks/base/services/java/com/android/server/SystemServer.java
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
WindowManagerService wm = null;
.......
InputManagerService inputManager = null;
.......
inputManager = new InputManagerService(context);//1
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore); //2
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());//4
inputManager.start();//5
- 创建了一个InputManagerService(为了方便,以后简称IMS)的实例,也是整个系统中的唯一实例;
- 将唯一的IMS传给WindowManagerService(简称WMS),这样WMS可以调用IMS所有的公有方法;
- 将IMS注册到系统服务中,这样可以通过Binder机制进行调用IMS;
- 将WMS的InputMonitor实例给IMS引用,InputMonitor负责输入事件的监控和焦点的管理等;
- 启动输入监控。
先简单总结下WMS和IMS的关系,以后一点一点完善:
实例化的过程
IMS的构造函数代码如下:
public InputManagerService(Context context) {
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());//1
.......
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());//2
......
}
- 创建一个Handler,可以注意到,其handler使用的Looper为DisplayThread的Looper,而此Looper同样被DisplayManagerService使用,另外WindowManagerService的实例化也是通过这个Looper运行的,其保证了他们之间不会并发。
- 调用nativeInit完成native的初始化。
IMS对应的native层的代码位置为:frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); //1
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper()); //2
im->incStrong(0);
return reinterpret_cast<jlong>(im);//3
}
sp<MessageQueue> android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) {
jlong ptr = env->GetLongField(messageQueueObj, gMessageQueueClassInfo.mPtr);
return reinterpret_cast<NativeMessageQueue*>(ptr);
}
- 将IMS的MessageQueue转化成native成的MessageQueue,并且java成的对象被保存到gMessageQueueClassInfo.mPtr引用中;
- 实例化一个NativeInputManager,以后IMS将会和这个实例打交道;
- 将第2步实例的指针传给IMS的mPtr全局变量保存。
再来看下NativeInputManager的构造函数:
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mContextObj = env->NewGlobalRef(contextObj);
mServiceObj = env->NewGlobalRef(serviceObj);//1
.......
sp<EventHub> eventHub = new EventHub();//2
mInputManager = new InputManager(eventHub, this, this);//3
}
- 将IMS的Context及IMS的实例以及IMS的Looper都保存了起来,这时,NativeInputManager和IMS的关系已变成生死与共了,IMS拥有NativeInputManager的指针地址,NativeInputManager又拥有IMS的唯一实例,同时也拥有其Looper;
- 实例化EventHub,EventHub监控,包装,分发具体的输入设备(主要是/dev/input下的节点),其代码位于frameworks/native/services/inputflinger/EventHub.cpp,先不看它。
- 实例化InputManager,又是一个重要的实例,下面看下它的构造函数。
frameworks/native/services/inputflinger/InputManager.cpp
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();
}
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
InputManager的构造函数创建了4个实例,mDispatcher及其mDispatcherThread,mReader和mReaderThread。另外InputManager构造函数中后两位形参InputReaderPolicyInterface和InputDispatcherPolicyInterface均指向的是同一个也是唯一的NativeInputManager实例。
总结下这些对象的关系:
运行IMS
在SystemServer中,inputManager.start():
public void start() {
nativeStart(mPtr);
.......
}
mPtr就是NativeInputManager实例。
static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
im->getInputManager()获得InputManager的实例:
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);//1
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputReader thread due to error %d.", result);
mDispatcherThread->requestExit();
return result;
}
return OK;
}
将InputDispatcherThread和InputReaderThread这两个线程启动了起来。
- 启动InputDispatcherThread线程
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
mDispatcher就是InputDispatcher。
- 启动InputReaderThread线程。
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
mReader为InputReader。
从名字上看,InputReader应该是负责读取输入事件,InputDispatcher应该是负责分发输入的事件,下面着重看下这两个类。另外InputDispatcherThread和InputReaderThread都是C++11的Thread子类,当Thread被start后,其threadLoop将会被调用,而且如果threadLoop返回的是true,threadLoop将会被一致循环调用,直到其返回false。目前它们一致返回的是ture,所以InputDispatcher的dispatchOnce和InputReader的loopOnce将会被一次一次的调用。
下面我们先看下输入事件的处理。
InputReader::loopOnce
void InputReader::loopOnce() {
......
// 1 从EventHub中获得输入事件的信息,将读取到的数据保存在mEventBuffer,返回值是读到的个数,该函数是阻塞的,如果没有事件,一致到超时才返回。
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{
.......
if (count) {
// 2 对读到到的数据进行处理
processEventsLocked(mEventBuffer, count);
}
...
}
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
// 如果设备发生改变,通知。mPolicy实际上就是NativeInputManager。
mPolicy->notifyInputDevicesChanged(inputDevices);
}
......
// 分发数据。
mQueuedListener->flush();
}
- EventHub通过linux的iNotify和EPoll机制查询输入设备的节点的事件,详细说这个东西需要较大的篇幅,先不看它;
- 将会对读取到的数据进行加工;
- 会将事件交给InputDispatcher进行分发。
看下数据的加工过程
InputReader::processEventsLocked
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) { //处理一般的输入事件
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1;
}
#if DEBUG_RAW_EVENTS
ALOGD("BatchSize: %d Count: %d", batchSize, count);
#endif
// 将来自于同一个输入设备的事件一块处理。
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else { //下面一些就是特殊的事件了,如增减设备等。
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
看下增加设备的代码:
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
//如果该设备已经添加,忽略。
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex >= 0) {
ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
return;
}
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
// 创建一个InputDevice的实例。
InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
device->configure(when, &mConfig, 0);
device->reset(when);
......
//将InputDevice增加到容器中。
mDevices.add(deviceId, device);
}
再看下对输入事件的处理:
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
......
InputDevice* device = mDevices.valueAt(deviceIndex);
if (device->isIgnored()) {
//ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
device->process(rawEvents, count);
}
调用InputDevice的process进行处理:
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
size_t numMappers = mMappers.size();
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
......
if (mDropUntilNextSync) {
......
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
......
} else {
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent);
}
}
}
}
mapper->process(rawEvent),这个maper是在运行增加设备的代码时,调用createDeviceLocked函数时为每种设备设置的mapper。
看下常见的KeyboardInputMapper:
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
int32_t scanCode = rawEvent->code;
int32_t usageCode = mCurrentHidUsage;
mCurrentHidUsage = 0;
if (isKeyboardOrGamepadKey(scanCode)) {
int32_t keyCode;
uint32_t flags;
if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
keyCode = AKEYCODE_UNKNOWN;
flags = 0;
}
// 处理按键值
processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
}
break;
}
......
}
}
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
int32_t scanCode, uint32_t policyFlags) {
......
// 通知按键值
getListener()->notifyKey(&args);
}
getListener()的值就是InputReader中的mQueuedListener,调用它的notifyKey实际上只是把键值保存到mQueuedListener的容器中。
mQueuedListener的类型是QueuedInputListener,它是在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);
{ // acquire lock
......
} // release lock
}
listener实际上是InputManager中InputDispatcher类型的mDispatcher。
QueuedInputListener的构造函数是:
QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
mInnerListener(innerListener) {
}
最后来到了InputReader::loopOnce节中的最后一步:
mQueuedListener->flush();
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
args->notify(mInnerListener);
delete args;
}
mArgsQueue.clear();
}
在通知按键值的时候:
getListener()->notifyKey(&args);
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
mArgsQueue.push(new NotifyKeyArgs(*args));
}
所以现在NotifyKeyArgs的notify函数将被调用:
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyKey(this);
}
到这时,InputDispatcher的notifyKey将被调用:
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
......
// 验证是否是键按下或抬起事件
if (!validateKeyEvent(args->action)) {
return;
}
......
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
......
} // release lock
if (needWake) {
mLooper->wake();
}
}
mPolicy就是NativeInputManager实例,而NativeInputManager的interceptKeyBeforeQueueing又会调用InputManagerService.java的interceptKeyBeforeQueueing,这样就又回到了Java层。