赞
踩
最近接触到了一个问题:耳机插入事件的由来,走读了下IMS输入系统服务的源码。同时,IMS输入系统服务在Android的开发过程中,也经常出现,有必要了解下相关原理。
常见的输入设备有鼠标、键盘、触摸屏等,用户通过输入设备与系统进行交互。
“uevent” 是 Linux 系统中的一种事件通知机制,用于向用户空间发送有关内核和设备状态变化的通知。这种机制通常用于设备驱动程序、热插拔事件以及设备状态变化等场景,以便用户空间应用程序能够在这些事件发生时做出相应的响应。
JNI,全称Java Native Interface,是Java编程语言的一种编程框架,用于实现Java代码与其他编程语言(如C、C++)进行交互的接口。JNI允许Java程序调用原生代码(native code),即由其他编程语言编写的代码,并且允许原生代码调用Java代码。通过JNI,Java程序可以访问底层系统功能、使用硬件设备、调用第三方库等。
监听多个描述符的可读/可写状态。等待返回时携带了可读的描述符
Linux 内核所提供的一种文件系统变化通知机制。可以监控文件系统的变化,如文件新建、删除、读写等
通过屏幕的触摸事件,来分析IMS系统,相关如下
| 层级 | 模块 | 描述 | 源码 | 编译产物 |
|---|---|---|---|---|
| Framework | InputManagerService | xxx | frameworks/base/services/core/java/ | out/target/product/qssi/system/framework/services.jar |
| Native | NativeInputManager | xxx | frameworks/base/services/core/jni/ | out/target/product/qssi/system/lib64/libandroid_servers.so |
| Native | Inputflinger | xxx | frameworks/native/services/inputflinger/ | out/target/product/qssi/system/lib64/libinputflinger.so |
| Native | Inputreader | xxx | frameworks/native/services/inputflinger/reader | out/target/product/qssi/system/lib64/libinputreader.so |
| Native | Inputdispatcher | xxx | frameworks/native/services/inputflinger/dispatcher/ | (静态库)out/soong/.intermediates/frameworks/native/services/inputflinger/dispatcher/libinputdispatcher/android_arm64_armv8-a_static/libinputdispatcher.a |
| Native | NativeInputEventReceiver | xxx | frameworks/base/core/jni/ | out/target/product/qssi/system/lib64/libandroid_runtime |
| Native | InputChannel | xxx | frameworks/native/libs/input/ | out/target/product/qssi/system/lib64/libinput.so |
InputManagerService是Android框架层一个非核心服务,主要是提供一个IMS输入系统启动的入口,同时对应用层提供业务相关接口。
Android设备开机后,会启动system_server进程,InputManagerService服务(以下简称IMS)在该进程被唤起。
@frameworks\base\services\java\com\android\server\SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context);//新建IMS实例
t.traceEnd();
...
t.traceBegin("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());//设置窗体事件监听
inputManager.start();//启动IMS服务
t.traceEnd();
...
}
此处做一些IMS相关的初始化操作,会调用nativeInit方法,获取一个NativeInputManager对象,类似于一个句柄。
@frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
public InputManagerService(Context context) {
...
mStaticAssociations = loadStaticInputPortAssociations();
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
...
}
InputManagerService通过start方法启动,会调用nativeStart方法,该方法为Native方法
@frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
private static native void nativeStart(long ptr);
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
...
}
该方法为Native的回调方法,用于上报IMS事件,如耳机插入事件等。
@frameworks\base\services\core\java\com\android\server\input\InputManagerService.java // Native callback. private void notifySwitch(long whenNanos, int switchValues, int switchMask) { ... if ((switchMask & SW_LID_BIT) != 0) { final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0); mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen); } if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) { final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0); mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered); } if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) { mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues, switchMask); } ... }
该模块为JNI模块,主要处理Java方法与c++方法映射关系,即IMS服务与InputFlinger模块的通信桥梁。
(1)新建一个NativeInputManager对象,并将该对象返回给java层
@\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);
...
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
(2)创建InputManager管理类,主要用于管理Input事件分发、事件读取行为
@\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();
...
mInputManager = new InputManager(this, this);
defaultServiceManager()->addService(String16("inputflinger"),
mInputManager, false);
}
获取上一个阶段创建NativeInputManager对象,并引用start启动该模块
@\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.");
}
}
input事件的管理类,数据传递类,也是输入系统native层核心的模块。
ps: 根据字典里的定义,flinger是指出轨的人。在SurfaceFlinger的例子中,它把可视数据扔给surface AudioFlinger把音频数据扔给适当的接收者。它们只是“可爱”的词…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。