该篇文章接总章,来详细谈论说明InputManagerService 体系,从初始化到事件获取跟分发。咱们在进行前,先明确哪几个问题需要知道,然后看看在这篇文章中是否解决了这些问题。对于InputManagerService,大家第一个想知道是他起什么作用,这个在总章里面有详细说明,简而言之就是获得事件跟分发处理事件。那他如何或者跟其他模块配合获取事件?并且把这个事件进行分发?如何准确定位对应的处理事件的模块?咱们下面开始讨论这些问题,在这个文章出来的时候,android 已经到N了 ,也就是7.0。但是由于我的笔记(初稿) 在M的时候已经完成了,也就是去年。所以这篇文章还是基于M (6.0)来写。
InputManagerService的初始化:
跟其他模块一样,作为系统的核心服务初始化在SystemServer。基本系统的核心服务都是在这里初始化,这个可以研究下系统的启动流程,在启动的最后就是需要启动所有的核心服务。
代码路径: frameworks/base/services/java/com/android/server/SystemServer.java
在run 方法里面,M 是在startOtherService()里面初始化InputManagerService
上面主要是新建IMS(InputManagerService 下面都用这个替换) 对象, 然后把WindowManagerService的InputMonitor作为参数传给IMS,重点关注下InputMonitor,这个跟事件的分发有关。然后在这里调用start方法启动IMS,这里的start 实际是调用 native 的start 方法。
看下InputManagerServices的start方法:
代码路径:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
上面主要调用了com_android_service_input_InputManagerService.cpp 里面的nativeStart方法,Java层的start方法主要做了两个工作:一个工作就是调用nativeStart方法。另外一个就是point 跟 toucher 相关参数设置跟监听,对应这Input事件的主要两类:Key 跟 toucher。在nativeStart里面的mPtr对应啥呢?首先Java层 跟 native层通信调用,主要通过JNI。这里主要是mPtr指针强制类型转换为NativeInputManager对象,看下源码:
Java层代码:
代码路径:frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
// Pointer to native input manager service object.
private final long mPtr;
public InputManagerService(Context context) {
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
//这里对mPtr 进行初始化,调用的还是native的方法,把这个service跟 Systemcontext 传给native对应的方法
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
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);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
} //这里把JAVA层的 Systemcontext 以及IMS自己 作为参数传过来了
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
这个为什么要把IMS 传给NativeInputManager呢?看下NativeInputManager的构造函数
代码路径:frameworks/base/services/core/jni/com_android_server_input_inputmanagerservice.cpp
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);
{
AutoMutex _l(mLock);
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
}
mInteractive = true;
//这个是从底层读取input 信息的提供者
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
这里有一个重要的对象就是EventHub,如总章所说这个对象是事件获取的重要的对象。在这里也对Native层的InputManager进行了初始化。前面解决了mPtr 是啥,nativeStart又干了啥?
InputManagerService的读取跟分发启动:
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
//这里就是上面获得InputManager对象调用start()方法返回的结果
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
查看下InputManager的start方法到底干了什么?frameworks/native/services/inputFlinger/InputManager.cpp
代码路径:frameworks/native/services/inputFlinger/InputManager.cpp
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
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;
}
嘿嘿,这里就真