本来想通过看老罗的书来学习这部分的源码,但实际对比发现8.0的android已经和老罗那时候的很大不一样,所以决定自己写一下,也当做笔记.
从名字就可以知道,InputManagerService是跟输入有关的,这不单单指键盘,只要是挂载在dev/input下面的设备都和它有关。
InputManagerService的启动
InputManagerService是在SystemServe
r的startOtherServices
中被初始化和启动的,此方法巨长,1200多行,我这里只贴和InputManagerService相关的部分。
private void startOtherServices() {
...
InputManagerService inputManager = null;
...
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);
traceEnd();
...
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
...
traceBeginAndSlog("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
traceEnd();
...
}
可以看到,首先会调用InputManagerService的构造函数。构造函数的源码如下:
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 = nativeInit(this, mContext, mHandler.getLooper().getQueue());
String doubleTouchGestureEnablePath = context.getResources().getString(
R.string.config_doubleTouchGestureEnableFile);
mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
new File(doubleTouchGestureEnablePath);
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
主要看如下这行
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
此行主要调用了nativeInit方法,来初始化,并返回一个指针地址,此方法的实现是在c++,如下
\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;
}
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
这里主要是new了一个NativeInputManager对象,此类的构造方法如下
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
...
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
做了两件事:
- 构造了一个EventHub对象,这个EventHub会去监听
dev/input
这个目录下文件的添加和删除,也就是输入设备的添加和删除,还会监听输入设备的输入事件 - 构造一个InputManager对象,并赋值给
mInputManager
全局变量,这个InputManager对象的构造会使用eventhub
作为参数。
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();
}
1.初始化了两个对象,mDispatcher
和mReader
,分别对应类InputDispatcher和InputReader,前者的作用是向当前激活的应用窗口分发输入事件,后者则是监控输入设备的事件。
2. 调用initialize()
方法
这个initialize()
方法的源码如下:
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
新建了两个分别为InputReaderThread和InputDispatcherThread类型的线程,这里先不研究线程的实现,先看下去。
到这里NativeInputManager类的构造函数就跑完了,生成的实例地址赋值给了im
变量,并强制转换成jlong
型的数据返回到java层的InputManagerService方法,并把返回值赋值给mPtr
变量。
再回到java层的SystemServer类的startOtherServices
方法:
private void startOtherServices() {
...
InputManagerService inputManager = null;
...
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);
traceEnd();
...
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
...
traceBeginAndSlog("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
traceEnd();
...
}
在新建一个InputManagerService对象并将对象赋值给inputManager
变量之后,会使用这个对象创建WindowManagerService,并将WindowManagerService的实力引用赋值给wm
变量,接着将wm
和inputManager
注册到ServiceManager中。
接下来会调用inputManager.start()
方法,也就是启动inputManager服务,我们看下具体源码
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
....
}
主要就是调用了nativeStart(mPtr)
,并加入看门狗监控,不用多说,nativeStart
又是一个native方法。实现如下
\frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp
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.");
}
}
就是调用了native层InputManager的start
方法,这个方法的实现如下
\frameworks\base\services\core\jni\com_android_server_input_InputManagerService.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;
}
可以看到,做的事情也很简单,就是启动了之前新建的两个线程。所以接下来就是看这两个线程做了什么。
到这里InputManagerService就启动完成了,可以发现主要代码都是在native层,其实核心的部分就是启动了两个线程,再下一篇就学习两个线程做了什么事情。