Android 输入系统(一)InputManagerService

由于之前做蓝牙hid的连接,以及输入事件的读取,突然想好好研究一下andorid输入事件到底是怎么管理的。

首先先看看系统服务InputManagerService的工作。以下都是基于Andorid4.3源码。

                                                                                                                                                                                                                              

InputManagerService产生

一般的系统服务是在SystemServer.javaServerThread中启动,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);
       ....
}

有上面代码总结其启动过程:

  1. 创建InputManagerService对象  
    InputManagerService初始化时传递了一个参数wmHandler,其创建如下
    HandlerThread wmHandlerThread = new HandlerThread(“WindowManager”);
            wmHandlerThread.start();
    Handler wmHandler = new Handler(wmHandlerThread.getLooper());
    这说明InputManagerService和WindowManagerService会有功能上的一些交互。
  2. 调用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构造函数中没有什么特别的东西,就不说了。

到这里输入系统的几个重要部分都创建完成了。如下是其结构图(网上找的)

《Android 输入系统(一)InputManagerService》


                                                                                                                                                                                                                              

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主要是调用InputManagerstart()方法,并将结果返回给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;
}

上述方法中工作就是将mDispatcherThreadmDispatcherThread线程开始运行。

待续。。。。。。。。。。

    原文作者:zpengyong
    原文地址: https://blog.csdn.net/vnanyesheshou/article/details/62221284
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞