Android input之IMS初始化

前言

在input子系统中,有两个主要角色,reader和dispatcher。前者通过EventHub读取input事件,然后将读取到的事件封装成rawevent放到queue中,而后者则是从该queue中拿rawevent并进行消费,对该事件进行分发,决定是否将该事件传递给应用。

InputReader和InputDispatcher是两个线程,先看看这两个家伙怎么启动的。然后再分别看是如何分工协作的。

IMS初始化

Android中用来处理输入相关的服务是InputManagerService,该服务在Android系统启动的过程中被SysetemService启动,具体启动位置在startOtherServices中:

//frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    ...
    InputManagerService inputManager = null;
    ...
    traceBeginAndSlog("StartInputManagerService");
         inputManager = new InputManagerService(context);
         traceEnd();
    ...
    traceBeginAndSlog("StartInputManager");
         inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
         inputManager.start();
         traceEnd();
    ...
}

这里只列出了InputManagerService相关的,在startOtherServices方法中,先new一个InputManagerService对象,然后调用它的start方法启动。我们直接看下InputManagerService的构造函数:

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
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()); //这里有个jni方法,有可能就是用来创建InputReader和InputDispatcher线程的

    String doubleTouchGestureEnablePath = context.getResources().getString(
            R.string.config_doubleTouchGestureEnableFile);
    mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
        new File(doubleTouchGestureEnablePath);

    LocalServices.addService(InputManagerInternal.class, new LocalService());
}

构造函数很简单,这里有个jni方法的调用,很可能就是用来创建InputReader和InputDispatcher线程的。它的实现如下:

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

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

这里创建了一个本地的InputManager,继续跟踪:

//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();

    mServiceObj = env->NewGlobalRef(serviceObj);

    {
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
        mLocked.pointerCapture = false;
        mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
    }
    mInteractive = true;

    mInputManager = new InputManager(this, this);
}

可以看到,NativeInputManager本身只是一层壳,真正有料的是InputManger,InputManager的实现如下:

//frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    mReader = createInputReader(readerPolicy, mClassifier);
    initialize();
}

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

终于看到,InputDispatcher和InputReader以及相应的mReaderThread和mDispatcherThread线程的创建。线程是载体,主要的做事人还是mDispatcher和mReader。
一张图总结:
在这里插入图片描述

IMS服务start

如上只是创建了InputReader和InputDispatcher对象和相应的线程,那在哪里启动的线程呢?InputManager中有一个start方法:

//frameworks/native/services/inputflinger/InputManager.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;
}

这里会调用两个线程的run方法,从而启动线程。而各自的threadLoop方法中,实际做了如下事情:

//frameworks/native/services/inputflinger/InputReaderBase.cpp
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}
//frameworks/native/services/inputflinger/InputDispatcher.cpp
bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce();
    return true;
}

各自跑到了InputReader和InputDispatcher的方法中。所以说线程只是个载体,真正的精华在InputReader和InputDispatcher类中。
如上的start方法,实际上也是java层的调用。SystemService在构造了InputManageService服务后,调用了它的start方法启动服务,方法实现如下:

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
 public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);
        ...
}

nativeStart是一个jni方法,在JNI层中的接口则直接调用了动态库libinputflinger中InputManager的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.");
    }
}

结语

如上就是IMS的初始化以及启动相关,在这个过程中,创建了InputReader对象和InputDispatcher对象以及对应的线程对象,线程只是载体,真正做事的是mReader和mDispatcher。接下来会单独对InputReader和InputDispatcher进行分析。

微信公众号

我在微信公众号也有写文章,更新比较及时。欢迎关注。关注有惊喜哦!
公众号名称为【Android系统实战开发】。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值