InputManagerService(输入办理服务)简称IMS,在安卓体系中担任它办理整个体系的输入部分,包括键盘、鼠标、触摸屏等等,它与WindowManager密切相关,IMS整体发动过程和重要方法如下图所示,本章将结合安卓11源码整理IMS的发动流程。
1、发动IMS服务
IMS发动流程坐落frameworks/base/services/java/com/android/server/SystemServer.java
,相关代码如下:
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
// 开始发动IMS
t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context);
t.traceEnd();
...
// 增加inputManager服务
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
...
// 发动InputManager
t.traceBegin("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
t.traceEnd();
}
2、IMS发动流程
IMS在SystemServer.java
中被发动后,会前往 frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
中持续其发动流程,IMS的发动过程如下:
public InputManagerService(Context context) {
this.mContext = context;
// 将InputManager参加"android.display"线程
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mStaticAssociations = loadStaticInputPortAssociations();
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
// 初始化native层InputManager
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());
}
// 设置window反应回调函数
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
if (mWindowManagerCallbacks != null) {
unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks);
}
mWindowManagerCallbacks = callbacks;
registerLidSwitchCallbackInternal(mWindowManagerCallbacks);
}
2.1、 native层初始化
由于IMS底层都是由C++实现的,故需要对native层的IMS进行初始化,active层的IMS初始化坐落frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// 获取messageQueue,该messageQueue由java传入, mHandler.getLooper().getQueue()
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
// 智能指针增加引用
im->incStrong(0);
// 转jlong返回
return reinterpret_cast<jlong>(im);
}
...
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
...
// 初始化InputManager
InputManager* im = new InputManager(this, this);
mInputManager = im;
defaultServiceManager()->addService(String16("inputflinger"), im);
}
2.2、 初始化InputManager
InputManager初始化inputDispatcher和InputReader,其初始化坐落frameworks/native/services/inputflinger/InputManager.cpp
:
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
// 初始化InputDispatcher
mDispatcher = new InputDispatcher(dispatcherPolicy);
// 初始化InputReader
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
2.3、 发动InputManager
InputManager在Native层初始化完毕后,将由java层调用其发动流程,该流程坐落frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
:
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
...
}
2.4、 发动native层InputManager
nativestart调用InputManager的start方法来运行线程,该部分代码坐落com_android_server_input_InputManagerService.cpp
:
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
// 将jlong转为NativeInputManager指针
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
// 获取InputManager并发动
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
// 发动运行 InputDispatcher(InputDispatcherThread) InputReader(InputReaderThread)线程
// frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {
// 发动dispatcher线程
status_t result = mDispatcher->start();
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
// 发动InputReader线程
result = mReader->start();
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;
}
2.5、InputDispatcher、InputReader 线程threadLoop
当native层InputManager发动InputDispatcher、InputReader线程后,这两个线程就会进入threadLoop环节,至此IMS发动完结。
// frameworks/native/services/inputflinger/InputDispatcher.cpp
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
// frameworks/native/services/inputflinger/InputReader.cpp
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
3、 总结
以上就是对IMS的发动总体流程做了大致的整理,现在总结出IMS发动流程的时序图,其中EventHub相关常识、input事情分发流程以及native层Input事情注入等重要环节将在之后的章节中重点评论。
四、参阅文章
- 《Android 输入子体系1:IMS 初始化与发动》
- 《Android InputManager剖析》