由于之前做蓝牙hid的连接,以及输入事件的读取,突然想好好研究一下andorid输入事件到底是怎么管理的。
首先先看看系统服务InputManagerService的工作。以下都是基于Andorid4.3源码。
InputManagerService产生
一般的系统服务是在SystemServer.java的ServerThread中启动,InputManagerService也不例外。
@Override
public void run() {
.....
Slog.i(TAG, "Input Manager");
//新建InputManagerService对象.
inputManager = new InputManagerService(context, wmHandler);
Slog.i(TAG, "Window Manager");
//这是窗口服务,先不说这个。
wm = WindowManagerService.main(context, power, display, inputManager,
uiHandler, wmHandler,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
//将InputManagerService添加到Serviceanager,便于其他用户访问
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
ActivityManagerService.self().setWindowManager(wm);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();//启动服务
display.setWindowManager(wm);
//向DisplayManagerService设置InputManagerService
display.setInputManager(inputManager);
....
}
有上面代码总结其启动过程:
- 创建InputManagerService对象
InputManagerService初始化时传递了一个参数wmHandler,其创建如下
HandlerThread wmHandlerThread = new HandlerThread(“WindowManager”);
wmHandlerThread.start();
Handler wmHandler = new Handler(wmHandlerThread.getLooper());
这说明InputManagerService和WindowManagerService会有功能上的一些交互。 - 调用InputManagerService的start函数。
InputManagerService 初始化工作
路径:frameworks/base/services/java/com/android/server/input/InputManagerService.java
创建InputManagerService对象,会先调用其构造函数。构造函数如下
public InputManagerService(Context context, Handler handler) {
this.mContext = context;
this.mHandler = new InputManagerHandler(handler.getLooper());
//获取config_useDevInputEventForAudioJack的值,该值为true,则通过inputEvent处理耳机插拔,否则通过UEent处理耳机插拔。默认为false。
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
//调用native方法进行初始化操作
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}
config_useDevInputEventForAudioJack设置是在frameworks/base/core/res/res/values/config.xml中
该值为TRUE使用Linux /dev/input/event子系统的变化来检测开关的耳机/麦克风插孔,值为假时使用uevent框架。默认false。
<!-- When true use the linux /dev/input/event subsystem to detect the switch changes
on the headphone/microphone jack. When false use the older uevent framework. -->
<bool name="config_useDevInputEventForAudioJack">false</bool>
nativeInit调用到com_android_server_input_InputManagerService.cpp文件中,
路径:frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp
nativeInit代码如下
static jint 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对象
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
//返回 NativeInputManager对象的指针
return reinterpret_cast<jint>(im);
}
nativeInit中主要是创建一个NativeInputManager对象,用来连接java层和native层。
NativeInputManager代码也在com_android_server_input_InputManagerService.cpp该文件中,接着看一下NativeInputManager的构造函数
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper) {
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;
}
//创建EventHub对象,该对象主要用来访问设备节点,获取输入事件、设备节点的添加和删除
sp<EventHub> eventHub = new EventHub();
//创建InputManager对象,管理InputReader与InputDispatcher.
mInputManager = new InputManager(eventHub, this, this);
}
EventHub先不说了,之后再抽时间研究研究。
InputManager
路径:frameworks/base/services/input/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();
}
接着看initialize()函数
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
创建一个InputReaderThread线程,供InputReader运行;
创建了一个InputDispatcherThread线程,供InputDispatcher运行。
InputDispatcher和InputReader构造函数中没有什么特别的东西,就不说了。
到这里输入系统的几个重要部分都创建完成了。如下是其结构图(网上找的)
InputManagerService启动
在SystemServer中调用InputManagerService的start()方法正式启动服务,函数如下:
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
//将inputmanagerservice添加到Wathcdog中,Watchdog检测service是否正常工作
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
//监听数据库中的Settings.System.POINTER_SPEED、Settings.System.SHOW_TOUCHES的变化,具体还不太清楚。
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
nativeStart()函数调用到com_android_server_input_InputManagerService.cpp中的nativeStart()函数
static void nativeStart(JNIEnv* env, jclass clazz, jint 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.");
}
}
nativeStart主要是调用InputManager的start()方法,并将结果返回给java层。接着看InputManager类中的start()方法。
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;
}
上述方法中工作就是将mDispatcherThread、mDispatcherThread线程开始运行。
待续。。。。。。。。。。