InputManagerService源码研究(一)service启动过程

本来想通过看老罗的书来学习这部分的源码,但实际对比发现8.0的android已经和老罗那时候的很大不一样,所以决定自己写一下,也当做笔记.
从名字就可以知道,InputManagerService是跟输入有关的,这不单单指键盘,只要是挂载在dev/input下面的设备都和它有关。

InputManagerService的启动

InputManagerService是在SystemServer的startOtherServices中被初始化和启动的,此方法巨长,1200多行,我这里只贴和InputManagerService相关的部分。

private void startOtherServices() {
...
InputManagerService inputManager = null;
...
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);
traceEnd();
...
wm = WindowManagerService.main(context, inputManager,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
        !mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
...
  traceBeginAndSlog("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
traceEnd();
...
}

可以看到,首先会调用InputManagerService的构造函数。构造函数的源码如下:

    public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        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());
    }

主要看如下这行

mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

此行主要调用了nativeInit方法,来初始化,并返回一个指针地址,此方法的实现是在c++,如下

\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);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

这里主要是new了一个NativeInputManager对象,此类的构造方法如下

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
...
    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}

做了两件事:

  1. 构造了一个EventHub对象,这个EventHub会去监听dev/input这个目录下文件的添加和删除,也就是输入设备的添加和删除,还会监听输入设备的输入事件
  2. 构造一个InputManager对象,并赋值给mInputManager全局变量,这个InputManager对象的构造会使用eventhub作为参数。

InputManager的构造函数代码如下:
\frameworks\native\services\inputflinger\InputManager.cpp

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

1.初始化了两个对象,mDispatchermReader,分别对应类InputDispatcher和InputReader,前者的作用是向当前激活的应用窗口分发输入事件,后者则是监控输入设备的事件。
2. 调用initialize()方法

这个initialize()方法的源码如下:

void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

新建了两个分别为InputReaderThread和InputDispatcherThread类型的线程,这里先不研究线程的实现,先看下去。

到这里NativeInputManager类的构造函数就跑完了,生成的实例地址赋值给了im变量,并强制转换成jlong型的数据返回到java层的InputManagerService方法,并把返回值赋值给mPtr变量。

再回到java层的SystemServer类的startOtherServices方法:

private void startOtherServices() {
...
InputManagerService inputManager = null;
...
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);
traceEnd();
...
wm = WindowManagerService.main(context, inputManager,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
        !mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
...
  traceBeginAndSlog("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
traceEnd();
...
}

在新建一个InputManagerService对象并将对象赋值给inputManager变量之后,会使用这个对象创建WindowManagerService,并将WindowManagerService的实力引用赋值给wm变量,接着将wminputManager注册到ServiceManager中。
接下来会调用inputManager.start()方法,也就是启动inputManager服务,我们看下具体源码

    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        ....
    }

主要就是调用了nativeStart(mPtr),并加入看门狗监控,不用多说,nativeStart又是一个native方法。实现如下

\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.");
    }
}

就是调用了native层InputManager的start方法,这个方法的实现如下
\frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp

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;
}

可以看到,做的事情也很简单,就是启动了之前新建的两个线程。所以接下来就是看这两个线程做了什么。

到这里InputManagerService就启动完成了,可以发现主要代码都是在native层,其实核心的部分就是启动了两个线程,再下一篇就学习两个线程做了什么事情。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章