Android 11.0源码系列之IMSInputManager

Posted bubbleben

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 11.0源码系列之IMSInputManager相关的知识,希望对你有一定的参考价值。

本篇涉及到的主要代码:

frameworks\\native\\services\\inputflinger

frameworks\\base\\services\\core\\android.bp

frameworks\\base\\services\\core\\jni\\Android.bp

frameworks\\base\\services\\core\\jni\\onload.cpp

frameworks\\base\\services\\core\\java\\com\\android\\server\\SystemServer.java

frameworks\\base\\services\\core\\java\\com\\android\\server\\input\\InputManagerService.java

frameworks\\base\\services\\core\\jni\\com_android_server_input_InputManagerService.cpp

上一篇我们已经介绍过Java层InputManagerService在系统启动时由SystemServer创建并启动,而且主要用于对native层InputManager的封装,所以本篇将分析native层InputManager的创建和启动过程。

根据上一篇文章的分析:InputManagerService在构造函数中调用了nativeInit方法,然后返回一个long型指针供Java层使用,由于它是一个native方法,所以根据通常的JNI文件命名方法查找到InputManagerService对应的JNI文件:com_android_server_input_InputManagerService.cpp

1.1 JNI方法的注册

[-> com_android_server_input_InputManagerService.cpp]

static const JNINativeMethod gInputManagerMethods[] = {
        /* name, signature, funcPtr */
        // 每一个数组中三个元素分别为:java层方法名,jni方法签名,jni方法
        {"nativeInit",
         "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/"
         "MessageQueue;)J",
         (void*)nativeInit},
        {"nativeStart", "(J)V", (void*)nativeStart},
        {"nativeRegisterInputChannel", "(JLandroid/view/InputChannel;)V",
         (void*)nativeRegisterInputChannel},
        {"nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
         (void*)nativeUnregisterInputChannel},
        {"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
         (void*)nativeSetFocusedApplication},
        {"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay},
};

这里只列出com_android_server_input_InputManagerService.cpp的部分JNI方法,包括nativeInit在内的所有其他方法都在gInputManagerMethods中声明和注册,那么gInputManagerMethods是何时以及如何加载的呢?这还得从SystemServer说起。

1.2 libandroid_servers.so的加载

[-> SystemServer.java]

private void run() {
    TimingsTraceAndSlog t = new TimingsTraceAndSlog();
    try {
        // Initialize native services.
        // 加载libandroid_servers.so
        System.loadLibrary("android_servers");

        // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }
    }
}

可以看到在启动系统各项关键服务之前,会先调用System.loadLibrary("android_servers")加载动态库,根据Gityuan "Android JNI原理分析"这篇文章http://gityuan.com/2016/05/28/android-jni/的分析,System.loadLibrary会先通过ClassLoader.findLibrary去查找名为libandroid_servers.so的库,那这个库是在哪里定义的呢?

[-> frameworks\\base\\services\\core\\Android.bp]

cc_library_shared {
    name: "libandroid_servers",
    defaults: ["libservices.core-libs"],
    whole_static_libs: ["libservices.core"],
}

在这里的Android.bp中定义了一个c++的库libandroid_servers.so,它依赖于libservices.core.so,而它又是在哪里定义的呢?

[-> frameworks\\base\\services\\core\\jni\\Android.bp]

cc_library_static {
    name: "libservices.core",
    defaults: ["libservices.core-libs"],

    srcs: [
        "com_android_server_input_InputManagerService.cpp",
        "onload.cpp",
    ],
}

这个库中定义了很多JNI文件,其中就包括com_android_server_input_InputManagerService.cpp,另外同样根据Gityuan这篇文章http://gityuan.com/2016/05/28/android-jni/分析:在找到so库之后System.loadLibrary最终会调用到相应库的JNI_OnLoad()方法;

[-> frameworks\\base\\services\\core\\jni\\onload.cpp]

extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
    JNIEnv* env = NULL;
    jint result = -1;
    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        ALOGE("GetEnv failed!");
        return result;
    }
    ALOG_ASSERT(env, "Could not retrieve the env!");

    ...
    register_android_server_InputManager(env);
    ...
    return JNI_VERSION_1_4;
}

onload.cppJNI_OnLoad()方法被触发之后,就会依次注册各项系统服务的JNI方法;

[-> com_android_server_input_InputManagerService.cpp]

int register_android_server_InputManager(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
            gInputManagerMethods, NELEM(gInputManagerMethods));
    (void) res;  // Faked use when LOG_NDEBUG.
    
        // Callbacks

    jclass clazz;
    // 获取到Java层InputManagerService的class,并将其赋值给gServiceClassInfo.clazz
    FIND_CLASS(clazz, "com/android/server/input/InputManagerService");
    gServiceClassInfo.clazz = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));

    // 获取Java层InputManagerService.notifyFocusChanged的方法id
    // 并将其赋值给gServiceClassInfo.notifyFocusChanged
    GET_METHOD_ID(gServiceClassInfo.notifyFocusChanged, clazz,
            "notifyFocusChanged", "(Landroid/os/IBinder;Landroid/os/IBinder;)V");

    // 获取Java层InputManagerService.notifyANR的方法id
    // 并将其赋值给gServiceClassInfo.notifyANR
    GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
            "notifyANR",
            "(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J");
}

void NativeInputManager::notifyFocusChanged(const sp<IBinder>& oldToken,
        const sp<IBinder>& newToken) {
    JNIEnv* env = jniEnv();

    jobject oldTokenObj = javaObjectForIBinder(env, oldToken);
    jobject newTokenObj = javaObjectForIBinder(env, newToken);
    // 这里的mServiceObj就是在1.3小节中介绍的Java层InputManagerService对象
    // 调用Java层InputManagerService.notifyFocusChanged方法
    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyFocusChanged,
            oldTokenObj, newTokenObj);
    checkAndClearExceptionFromCallback(env, "notifyFocusChanged");
}

到这里我们熟悉的gInputManagerMethods又出现了,前面我们提到它承载的就是com_android_server_input_InputManagerService所有的JNI方法,jniRegisterNativeMethods方法最终会完成gInputManagerMethods数组中所有java方法和jni方法的映射关系,比如Java层的nativeInit()方法,会映射到JNI层的com_android_server_input_InputManagerService_nativeInit()方法;随后通过FIND_CLASS拿到Java层InputManagerService的class,然后获取并保存其特定方法的id,这样就可以在JNI中调用Java中的方法,所以在所有JNI方法都注册完成之后再去启动所有系统服务,这样不管是在Java还是JNI中都可以相互调用对方的方法了;

1.3 NativeInputManager的创建

[-> com_android_server_input_InputManagerService.cpp]

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    // 获取Java层绑定"android.display"线程的MessageQueue转换成native层的NativeMessageQueue
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    
    // 将Java层的InputManagerService和NativeMessageQueue对应的Looper作为参数来构造NativeInputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    // 强引用计数加一
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    // 保存Java层InputManagerService对象,然后通过它就可以在native调用Java的方法
    mServiceObj = env->NewGlobalRef(serviceObj);
    ...
    // 创建native层InputManager并将其作为名为"inputflinger"的系统服务添加到ServiceManager
    mInputManager = new InputManager(this, this);
    defaultServiceManager()->addService(String16("inputflinger"),
            mInputManager, false);
}

回到nativeInit方法,它主要的作用就是创建NativeManagerInputManager,而InputManager位于libinputflinger.so中,拿到它之后就打通了input子系统从Java–>JNI–>Native的通道;

1.4 InputManager的创建

[-> frameworks\\native\\services\\inputflinger\\InputManager.cpp]

InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    // 创建InputDispatcher
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    // 创建InputClassifier
    mClassifier = new InputClassifier(mDispatcher);
    // 创建InputReader
    mReader = createInputReader(readerPolicy, mClassifier);
}

注意这里的readerPolicydispatcherPolicy都是指NativeInputManager

[-> frameworks\\native\\services\\inputflinger\\InputClassifier.cpp]

// --- InputClassifier ---

InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
      : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}

将传入的InputDispatcher作为InputListenerInterface赋值给mListener,这个接口负责将InputReader读取的输入事件传递给InputDispatcher来分发,我们会在接下来一篇文章中详细介绍;

[-> frameworks\\native\\services\\inputflinger\\InputDispathcer.cpp]

sp<InputDispatcherInterface> createInputDispatcher(
        const sp<InputDispatcherPolicyInterface>& policy) {
    return new android::inputdispatcher::InputDispatcher(policy);
}

[-> frameworks\\native\\services\\inputflinger\\InputReaderFactory.cpp]

sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
                                           const sp<InputListenerInterface>& listener) {
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}

这里我们先简单介绍一下InputReaderInputClassifierInputDispatcher,关于它们更详细的初始化过程和作用后面我们会以单独的篇幅来介绍;到这里NativeInputManagerInputManager已经创建完成,在上一篇文章中我们分析过InputManagerService创建完成后会调用nativeStart方法,接下来我们看看它又做了哪些事情?

1.5 InputManager的启动

[-> frameworks\\native\\services\\inputflinger\\InputManager.cpp]

status_t InputManager::start() {
    // 启动InputDispatcher对应的线程
    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;
}

可以看到InputDispathcerInputReader启动了2个非常重要的线程,它们确保了input子系统能够源源不断的从底层获取输入事件,并将事件经过层层包装之后上报给当前的焦点窗口去处理,关于InputDispatcherInputReader会在下一篇文章中详细介绍。

总结

本篇主要介绍Native层InputManager的创建,以nativeInit为例分析了从Java到JNI最后到native层的整个调用过程,到目前为止input相关的准备工作都已经完成,至于native层是如何获取input事件以及如何分发到应用进程的,我们会在接下来的篇幅中慢慢为大家揭晓。

以上是关于Android 11.0源码系列之IMSInputManager的主要内容,如果未能解决你的问题,请参考以下文章

Android 11.0源码系列之PMSinstalld

Android 11.0源码系列之IMSInputManagerService

Android 11.0源码系列之IMSInputManager

Android 11.0源码系列之IMSInputDispatcher

Android 11.0源码系列之PMSPackageManagerService的创建

Android 11.0源码系列之IMSInputReader