Android 12.0源码系列之IMSInputManager
Posted bubbleben
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 12.0源码系列之IMSInputManager相关的知识,希望对你有一定的参考价值。
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
创建并启动,本篇将继续分析native
层InputManager
的创建和启动过程。
1. gInputManagerMethods
根据上一篇文章的分析:InputManagerService
在构造函数中调用了nativeInit
方法返回一个指向NativeInputManager
的指针mPtr
,nativeInit
是一个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)
方法;
随后注册JNI
到Java
层的回调:通过FIND_CLASS
获取Java
层InputManagerService
并将其保存到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
除了保存Java
层InputManagerService
的clazz
以外,还保存了其所有方法对应的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
会先回调NativeInputManager
的notifyFocusChanged
,最终回调给InputManagerService
的notifyFocusChanged
方法;
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
同时继承了InputReaderPolicyInterface
和InputDispatcherPolicyInterface
,所以这里的readerPolicy
和dispatcherPolicy
都是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
用于对输入事件的分类,至此NativeInputManager
和InputManager
已经创建完成;
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;
这里启动了非常重要的两个线程:InputDispatcher
和InputReader
,它们确保input
子系统能够源源不断的从底层获取各类输入事件,并将事件经过层层封装之后上报给当前的焦点窗口去处理,关于InputDispatcher
和InputReader
会在下一篇文章中详细介绍。
以上是关于Android 12.0源码系列之IMSInputManager的主要内容,如果未能解决你的问题,请参考以下文章
Android 12.0源码系列之IMSInputManagerService
Android 12.0源码系列之IMSInputManagerService
Android 11.0源码系列之IMSInputChannel
原Android热更新开源项目Tinker源码解析系列之三:so热更新