Android Framework重要服务之InputManagerService(一) 启动流程

InputManagerService(输入管理服务)简称IMS,在安卓系统中负责它管理整个系统的输入部分,包括键盘、鼠标、触摸屏等等,它与WindowManager密切相关,本章将结合安卓11源码梳理IMS的启动流程。

一、启动IMS服务

IMS启动流程位于frameworks/base/services/java/com/android/server/SystemServer.java,相关代码如下:

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
    
    // 开始启动IMS
    t.traceBegin("StartInputManagerService");
    inputManager = new InputManagerService(context);
    t.traceEnd();
    ...
    
    // 添加inputManager服务
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    ...
    
    // 启动InputManager
    t.traceBegin("StartInputManager");
    inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
    inputManager.start();
    t.traceEnd();
} 

二、IMS启动流程

IMS在SystemServer.java中被启动后,会前往 frameworks/base/services/core/java/com/android/server/input/InputManagerService.java 中继续其启动流程,IMS的启动过程如下:

public InputManagerService(Context context) {
    this.mContext = context;
    // 将InputManager加入"android.display"线程
    this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

    mStaticAssociations = loadStaticInputPortAssociations();
    mUseDevInputEventForAudioJack =
            context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
    Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
            + mUseDevInputEventForAudioJack);
            
    // 初始化native层InputManager
    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());
}

// 设置window反馈回调函数
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
    if (mWindowManagerCallbacks != null) {
        unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks);
    }
    mWindowManagerCallbacks = callbacks;
    registerLidSwitchCallbackInternal(mWindowManagerCallbacks);
} 

1. native层初始化

由于IMS底层都是由C++实现的,故需要对native层的IMS进行初始化,ative层的IMS初始化位于frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
        // 获取messageQueue,该messageQueue由java传入, mHandler.getLooper().getQueue()
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);   
 
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    // 智能指针增加引用
    im->incStrong(0);  
    // 转jlong返回
    return reinterpret_cast<jlong>(im);   
}
...
 
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    ...
    
    // 初始化InputManager
    InputManager* im = new InputManager(this, this);
    mInputManager = im;
    defaultServiceManager()->addService(String16("inputflinger"), im);
} 
  1. 初始化InputManager

InputManager初始化inputDispatcher和InputReader,其初始化位于frameworks/native/services/inputflinger/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();
} 

3. 启动InputManager

InputManager在Native层初始化完毕后,将由java层调用其启动流程,该流程位于frameworks/base/services/core/java/com/android/server/input/InputManagerService.java:

public void start() {
    Slog.i(TAG, "Starting input manager");
    nativeStart(mPtr);
 
    // Add ourself to the Watchdog monitors.
    Watchdog.getInstance().addMonitor(this);
    ...
    
} 

4. 启动native层InputManager

nativestart调用InputManager的start方法来运行线程,该部分代码位于com_android_server_input_InputManagerService.cpp:

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    // 将jlong转为NativeInputManager指针
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    
    // 获取InputManager并启动
    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}
 
// 启动运行 InputDispatcher(InputDispatcherThread)  InputReader(InputReaderThread)线程
// frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {
    // 启动dispatcher线程
    status_t result = mDispatcher->start();
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }
    
    // 启动InputReader线程
    result = mReader->start();
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);

        mDispatcher->stop();
        return result;
    }

    return OK;
} 

InputDispatcher、InputReader 线程threadLoop

当native层InputManager启动InputDispatcher、InputReader线程后,这两个线程就会进入threadLoop环节,至此IMS启动完成。

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

三、 总结

以上就是对IMS的启动总体流程做了大致的梳理,现在总结出IMS启动流程的时序图,其中EventHub相关知识、input事件分发流程以及native层Input事件注入等重要环节将在之后的章节中重点讨论。

image.png

文末

我总结了一些Android核心知识点,以及一些最新的大厂面试题、知识脑图和视频资料解析。

需要的小伙伴直接点击文末小卡片可以领取哦!我免费分享给你,以后的路也希望我们能一起走下去。(谢谢大家一直以来的支持,需要的自己领取)

Android学习PDF+架构视频+面试文档+源码笔记

部分资料一览:

  • 330页PDF Android学习核心笔记(内含8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT大厂面试题(有解析)

点击下方卡片免费领取

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值