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内容请搜索靠谱客的其他文章。
发表评论 取消回复