概述
Android 12.0源码系列之IMS(二)InputManager
本篇涉及到的主要代码:
frameworksnativeservicesinputflinger
frameworksbaseservicescoreAndroid.bp
frameworksbaseservicescorejniAndroid.bp
frameworksbaseservicescorejnionload.cpp
frameworksbaseservicescorejavacomandroidserverSystemServer.java
frameworksbaseservicescorejnicom_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
的库,那这个库是在哪里定义的呢?
[-> frameworksbaseservicescoreAndroid.bp]
cc_library_shared {
name: "libandroid_servers",
defaults: ["libservices.core-libs"],
whole_static_libs: ["libservices.core"],
}
这里定义了一个c++
的库libandroid_servers.so
,它依赖于libservices.core.so
,而它又是在哪里定义的呢?
[-> frameworksbaseservicescorejniAndroid.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
[-> frameworksnativeservicesinputflingerAndroid.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源码系列之IMS(二)InputManagerAndroid 12.0源码系列之IMS(二)InputManager的全部内容,希望文章能够帮你解决Android 12.0源码系列之IMS(二)InputManagerAndroid 12.0源码系列之IMS(二)InputManager所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复