和你一起终身学习,这里是程序员Android
经典好文推荐,通过阅读本文,您将收获以下知识点:
一、前言
二、启动流程
2.1 创建输入系统
2.2 启动输入系统
2.3 输入系统就绪
一、前言
之前写过几篇关于输入系统的文章,但是还没有写完,后来由于工作的变动,这个事情就一直耽搁了。而现在,在工作中,遇到输入系统相关的事情也越来越多,其中有一个非常有意思的需求,因此是时候继续分析 InputManagerService。
InputManagerService 系统文章,基于 Android 12 进行分析。
本文将以 IMS 简称 InputManagerService。
二、启动流程
InputManagerService 是一个系统服务,启动流程如下
// SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
// ..
// 1. 创建
inputManager = new InputManagerService(context);
// 注册服务
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
// 保存 wms 的回调
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
// 2. 启动
inputManager.start();
try {
// 3. 就绪
if (inputManagerF != null) {
inputManagerF.systemRunning();
}
} catch (Throwable e) {
reportWtf("Notifying InputManagerService running", e);
}
// ...
}
IMS 的启动流程分为三步
1.创建输入系统,建立上层与底层的映射关系。
2.启动输入系统,其实就是启动底层输入系统的几个模块。
3.输入系统就绪,上层会同步一些配置给底层输入系统。
下面分三个模块,分别讲解这三步。
2.1 创建输入系统
// InputManagerService.java
public InputManagerService(Context context) {
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
// 配置为空
mStaticAssociations = loadStaticInputPortAssociations();
// 默认 false
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
// 1. 底层进行初始化
// mPtr 指向底层创建的 NativeInputManager 对象
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
// 空
String doubleTouchGestureEnablePath = context.getResources().getString(
R.string.config_doubleTouchGestureEnableFile);
// null
mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
new File(doubleTouchGestureEnablePath);
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
IMS 构造函数,主要就是调用 nativeInit() 来初始化底层输入系统。
// com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueu