Step 6. InputManager.nativeInit
这个函数定义在frameworks/base/services/jni$ vi com_android_server_InputManager.cpp文件中:
- static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
- jobject callbacks) {
- if (gNativeInputManager == NULL) {
- gNativeInputManager = new NativeInputManager(callbacks);
- } else {
- LOGE("Input manager already initialized.");
- jniThrowRuntimeException(env, "Input manager already initialized.");
- }
- }
这个函数的作用是创建一个NativeInputManager实例,并保存在gNativeInputManager变量中。由于是第一次调用到这里,因此,gNativeInputManager为NULL,于是就会new一个NativeInputManager对象出来,这样就会执行NativeInputManager类的构造函数来执其它的初始化操作。
Step 7. NativeInputManager<init>
NativeInputManager类的构造函数定义在frameworks/base/services/jni$ vi com_android_server_InputManager.cpp文件中:
- NativeInputManager::NativeInputManager(jobject callbacksObj) :
- mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
- mMaxEventsPerSecond(-1),
- mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0) {
- JNIEnv* env = jniEnv();
-
- mCallbacksObj = env->NewGlobalRef(callbacksObj);
-
- sp<EventHub> eventHub = new EventHub();
- mInputManager = new InputManager(eventHub, this, this);
- }
这里只要是创建了一个EventHub实例,并且把这个EventHub作为参数来创建InputManager对象。注意,这里的InputManager类是定义在C++层的,和前面在Java层的InputManager不一样,不过它们是对应关系。EventHub类是真正执行监控键盘事件操作的地方,后面我们会进一步分析到,现在我们主要关心InputManager实例的创建过程,它会InputManager类的构造函数里面执行一些初始化操作。
Step 8. InputManager<init>@C++
C++层的InputManager类的构造函数定义在frameworks/base/libs/ui/InputManager.cpp 文件中:
- InputManager::InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = new InputDispatcher(dispatcherPolicy);
- mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
- initialize();
- }
这里主要是创建了一个InputDispatcher对象和一个InputReader对象,并且分别保存在成员变量mDispatcher和mReader中。InputDispatcher类是负责把键盘消息分发给当前激活的Activity窗口的,而InputReader类则是通过EventHub类来实现读取键盘事件的,后面我们会进一步分析。创建了这两个对象后,还要调用initialize函数来执行其它的初始化操作。
Step 9. InputManager.initialize
这个函数定义在frameworks/base/libs/ui/InputManager.cpp 文件中:
- void InputManager::initialize() {
- mReaderThread = new InputReaderThread(mReader);
- mDispatcherThread = new InputDispatcherThread(mDispatcher);
- }
这个函数创建了一个InputReaderThread线程实例和一个InputDispatcherThread线程实例,并且分别保存在成员变量mReaderThread和mDispatcherThread中。这里的InputReader实列mReader就是通过这里的InputReaderThread线程实列mReaderThread来读取键盘事件的,而InputDispatcher实例mDispatcher则是通过这里的InputDispatcherThread线程实例mDisptacherThread来分发键盘消息的。
至此,InputManager的初始化工作就完成了,在回到Step 3中继续分析InputManager的进一步启动过程之前,我们先来作一个小结,看看这个初始化过程都做什么事情:
A. 在Java层中的WindowManagerService中创建了一个InputManager对象,由它来负责管理Android应用程序框架层的键盘消息处理;
B. 在C++层也相应地创建一个InputManager本地对象来负责监控键盘事件;
C. 在C++层中的InputManager对象中,分别创建了一个InputReader对象和一个InputDispatcher对象,前者负责读取系统中的键盘消息,后者负责把键盘消息分发出去;
D. InputReader对象和一个InputDispatcher对象分别是通过InputReaderThread线程实例和InputDispatcherThread线程实例来实键盘消息的读取和分发的。
有了这些对象之后,万事就俱备了,回到Step 3中,调用InputManager类的start函数来执行真正的启动操作。
Step 10. InputManager.start
这个函数定义在frameworks/base/services/java/com/android/server/InputManager.java文件中:
- public class InputManager {
- ......
-
- public void start() {
- Slog.i(TAG, "Starting input manager");
- nativeStart();
- }
-
- ......
- }
这个函数通过调用本地方法nativeStart来执行进一步的启动操作。
Step 11. InputManager.nativeStart
这个函数定义在frameworks/base/services/jni$ vi com_android_server_InputManager.cpp文件中:
- static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
- if (checkInputManagerUnitialized(env)) {
- return;
- }
-
- status_t result = gNativeInputManager->getInputManager()->start();
- if (result) {
- jniThrowRuntimeException(env, "Input manager could not be started.");
- }
- }
这里的gNativeInputManager对象是在前面的Step 6中创建的,通过它的getInputManager函数可以返回C++层的InputManager对象,接着调用这个InputManager对象的start函数。
Step 12. InputManager.start
这个函数定义在frameworks/base/libs/ui/InputManager.cpp 文件中:
- status_t InputManager::start() {
- status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
- if (result) {
- LOGE("Could not start InputDispatcher thread due to error %d.", result);
- return result;
- }
-
- result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
- if (result) {
- LOGE("Could not start InputReader thread due to error %d.", result);
-
- mDispatcherThread->requestExit();
- return result;
- }
-
- return OK;
- }
这个函数主要就是分别启动一个InputDispatcherThread线程和一个InputReaderThread线程来读取和分发键盘消息的了。这里的InputDispatcherThread线程对象mDispatcherThread和InputReaderThread线程对象是在前面的Step 9中创建的,调用了它们的run函数后,就会进入到它们的threadLoop函数中去,只要threadLoop函数返回true,函数threadLoop就会一直被循环调用,于是这两个线程就起到了不断地读取和分发键盘消息的作用。
我们先来分析InputDispatcherThread线程分发消息的过程,然后再回过头来分析InputReaderThread线程读取消息的过程。
Step 13. InputDispatcherThread.threadLoop
这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中:
- bool InputDispatcherThread::threadLoop() {
- mDispatcher->dispatchOnce();
- return true;
- }
这里的成员变量mDispatcher即为在前面Step 8中创建的InputDispatcher对象,调用它的dispatchOnce成员函数执行一次键盘消息分发的操作。
Step 14. InputDispatcher.dispatchOnce
这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中:
- void InputDispatcher::dispatchOnce() {
- nsecs_t keyRepeatTimeout = mPolicy->getKeyRepeatTimeout();
- nsecs_t keyRepeatDelay = mPolicy->getKeyRepeatDelay();
-
- nsecs_t nextWakeupTime = LONG_LONG_MAX;
- {
- AutoMutex _l(mLock);
- dispatchOnceInnerLocked(keyRepeatTimeout, keyRepeatDelay, & nextWakeupTime);
-
- if (runCommandsLockedInterruptible()) {
- nextWakeupTime = LONG_LONG_MIN;
- }
- }
-
-
- nsecs_t currentTime = now();
- int32_t timeoutMillis;
- if (nextWakeupTime > currentTime) {
- uint64_t timeout = uint64_t(nextWakeupTime - currentTime);
- timeout = (timeout + 999999LL) / 1000000LL;
- timeoutMillis = timeout > INT_MAX ? -1 : int32_t(timeout);
- } else {
- timeoutMillis = 0;
- }
-
- mLooper->pollOnce(timeoutMillis);
- }
这个函数很简单,把键盘消息交给dispatchOnceInnerLocked函数来处理,这个过程我们在后面再详细分析,然后调用mLooper->pollOnce函数等待下一次键盘事件的发生。这里的成员变量mLooper的类型为Looper,它定义在C++层中,具体可以参考前面Android应用程序消息处理机制(Looper、Handler)分析一文。