Android 12.0源码系列之IMS(二)InputManager

Android 12.0源码系列之IMS(二)InputManager

本篇涉及到的主要代码:

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\jni\com_android_server_input_InputManagerService.cpp

上一篇我们介绍了InputManagerService在系统启动时由SystemServer创建并启动,本篇将继续分析nativeInputManager的创建和启动过程。

1. gInputManagerMethods

根据上一篇文章的分析:InputManagerService在构造函数中调用了nativeInit方法返回一个指向NativeInputManager的指针mPtrnativeInit是一个native方法,根据通常JNI文件命名方法查找到InputManagerService对应的JNI文件:com_android_server_input_InputManagerService.cpp,这个native方法就定义在其中的gInputManagerMethods中;

[-> com_android_server_input_InputManagerService.cpp]

static const JNINativeMethod gInputManagerMethods[] = {
    /* name, signature, funcPtr */
    // 初始InputManager以及InputReader和InputDispatcher
    {"nativeInit",
     "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/"
     "MessageQueue;)J",
     (void*)nativeInit},
    // 启动InputReader和InputDispatcher线程
    {"nativeStart", "(J)V", (void*)nativeStart},
    // 对应Android 11.0 nativeRegisterInputChannel
    {"nativeCreateInputChannel", "(JLjava/lang/String;)Landroid/view/InputChannel;",
     (void*)nativeCreateInputChannel},
    // 对应Android 11.0 nativeUnregisterInputChannel         
    {"nativeRemoveInputChannel", "(JLandroid/os/IBinder;)V", (void*)nativeRemoveInputChannel},
    // 设置焦点应用
    {"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
     (void*)nativeSetFocusedApplication},
    // 设置焦点逻辑屏 
    {"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay},
};

这里只列出gInputManagerMethods数组中声明的部分方法,其中每一个元素都包含Java层方法名,JNI方法签名和JNI方法名,它们是何时以及如何加载的呢?这还得从SystemServer的启动说起。

2. NativeInputManager
2.1 System.loadLibrary

[-> SystemServer.java]

private void run() {
    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
        }
    }
}

SystemServer在启动系统各项关键服务之前,会先通过System.loadLibrary("android_servers")加载动态库,根据 [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"],
}

这里定义了一个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,在找到对应的so库之后System.loadLibrary最终会调用到对应库的JNI_OnLoad()方法;

2.2 onload.JNI_OnLoad

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

    register_android_server_PowerManagerService(env);
    register_android_server_PowerStatsService(env);
    register_android_server_HintManagerService(env);
    register_android_server_SerialService(env);
    // 注册InputManagerService的JNI方法
    register_android_server_InputManager(env);
    register_android_server_LightsService(env);
    register_android_server_UsbDeviceManager(env);
    register_android_server_UsbMidiDevice(env);
    register_android_server_UsbAlsaJackDetector(env);
    register_android_server_UsbHostManager(env);

    return JNI_VERSION_1_4;
}

JNI_OnLoad()方法被触发之后就会依次注册各系统服务的JNI方法;

2.3 register_android_server_InputManager

[-> 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));
    
    // 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");
}

到这里我们熟悉的gInputManagerMethods又出现了,前面我们提到它承载的就是com_android_server_input_InputManagerService所有的JNI方法:jniRegisterNativeMethods方法最终会完成gInputManagerMethods数组中所有Java方法与JNI方法的映射,比如Java层的nativeInit(InputManagerService service, Context context, MessageQueue messageQueue)方法,会映射到jni层的nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj, jobject contextObj, jobject messageQueueObj)方法;

随后注册JNIJava层的回调:通过FIND_CLASS获取JavaInputManagerService并将其保存到gServiceClassInfo结构体中,然后获取并保存所有回调方法的jmethodID,这样就可以在JNI中回调Java中的方法,所以在所有JNI方法都注册完成之后再去启动系统服务,这样不管是在Java还是JNI层中都可以相互调用对方的方法;

static struct {
    jclass clazz;
    jmethodID notifyConfigurationChanged;
    jmethodID notifyInputDevicesChanged;
    jmethodID notifySwitch;
    jmethodID notifyInputChannelBroken;
    jmethodID notifyNoFocusedWindowAnr;
    jmethodID notifyFocusChanged;
    jmethodID interceptKeyBeforeQueueing;
    jmethodID interceptMotionBeforeQueueingNonInteractive;
    jmethodID interceptKeyBeforeDispatching;
} gServiceClassInfo;

gServiceClassInfo除了保存JavaInputManagerServiceclazz以外,还保存了其所有方法对应的jmethodID

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

    // 将native层的IBinder转换未Java层的IBinder对象
    jobject oldTokenObj = javaObjectForIBinder(env, oldToken);
    jobject newTokenObj = javaObjectForIBinder(env, newToken);
    // 这里的mServiceObj就是Java层InputManagerService对象
    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyFocusChanged,
            oldTokenObj, newTokenObj);
}

notifyFocusChanged为例:InputDispatcher会先回调NativeInputManagernotifyFocusChanged,最终回调给InputManagerServicenotifyFocusChanged方法;

2.4 nativeInit

[-> 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);
    
    // 将Java层的InputManagerService和native的Looper作为参数来构造NativeInputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    // 增加强引用计数
    im->incStrong(0);
    // 将NativeInputManager强转成jlong型的指针
    return reinterpret_cast<jlong>(im);
}

回到nativeInit方法,它创建了NativeInputManager

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

它创建了InputManager,并以inputflinger为别名添加到service_manager中;

3. InputManager

[-> frameworks\native\services\inputflinger\Android.bp]

cc_library_shared {
    name: "libinputflinger",
    defaults: [
        "inputflinger_defaults",
        "libinputflinger_defaults",
    ],
}

InputManager位于libinputflinger.so,至此input子系统从Java经过JNI来到了Native

[-> InputManager.cpp]

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

NativeInputManager同时继承了InputReaderPolicyInterfaceInputDispatcherPolicyInterface,所以这里的readerPolicydispatcherPolicy都是NativeInputManager

3.1 InputClassifier

[-> InputClassifier.cpp]

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

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

3.2 InputDispathcerFactory

[-> InputDispathcerFactory.cpp]

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

创建InputDispatcher:传入NativeInputManager作为inputflinger回调JNI的工具;

3.3 InputReaderFactory

[-> InputReaderFactory.cpp]

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

创建InputReader:传入NativeInputManager作为inputflinger回调JNI的工具,InputClassifier用于对输入事件的分类,至此NativeInputManagerInputManager已经创建完成;

3.4 nativeStart

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

在上一篇文章中我们分析过InputManagerService创建完后会调用nativeStart方法,而它又调用了InputManager.start方法;

[-> InputManager.cpp]

status_t InputManager::start() {
    // 启动InputDispatcher线程
    status_t result = mDispatcher->start();

    // 启动InputReader线程
    result = mReader->start();

    return OK;
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值