Step 19. InputManager.unregisterInputChannel
这个函数定义在frameworks/base/services/java/com/android/server/InputManager.java文件中:
- public class InputManager {
- ......
- public void unregisterInputChannel(InputChannel inputChannel) {
- ......
- nativeUnregisterInputChannel(inputChannel);
- }
- ......
- }
这个函数很简单,它调用本地方法nativeUnregisterInputChannel来进一步处理。
Step 20. InputManager.nativeUnregisterInputChannel
这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp文件中:
- static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
- jobject inputChannelObj) {
- ......
- sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
- inputChannelObj);
- ......
- status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
- ......
- }
这个函数首先调用android_view_InputChannel_getInputChannel函数根据Java层的InputChannel对象找到C++层的InputChannel对象,然后调用NativeInputManager的unregisterInputChannel函数来执行注销的操作。
Step 21. NativeInputManager.unregisterInputChannel
这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp文件中:
- status_t NativeInputManager::unregisterInputChannel(JNIEnv* env,
- const sp<InputChannel>& inputChannel) {
- ......
- return mInputManager->getDispatcher()->unregisterInputChannel(inputChannel);
- }
这个函数与前面分析应用程序注册键盘消息通道的Step 17(NativeInputManager.registerInputChannel)相对应,主要是调用InputDispatcher对象的unregisterInputChannel函数来执行真正注销的操作。
Step 22. InputDispatcher.unregisterInputChannel
这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中:
- status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
- ......
- { // acquire lock
- AutoMutex _l(mLock);
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- ......
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
- ......
- mLooper->removeFd(inputChannel->getReceivePipeFd());
- .....
- } // release lock
- ......
- return OK;
- }
这一步与前面的Step 14注销应用程序一侧的Client端InputChannel是差不多的,只不过这里是从InputDispatcher中把Server端的InputChannel注销掉。首先是根据传进来的参数inputChannel找到它在InputDispatcher中对应的Connection对象在mConnectionsByReceiveFd中的索引,然后把它从mConnectionsByReceiveFd中删除:
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- ......
- sp<Connection> connection = mConnectionsByReceiveFd.valueAt(connectionIndex);
- mConnectionsByReceiveFd.removeItemsAt(connectionIndex);
最后,还需要把这个InputChannel中的反向管道读端文件描述符从InputDispatcher的内部对象mLooper中删除,因为这个文件描述符是在前面注册Server端的InputChannel时加入到mLooper对象去的,具体可以参考上面分析应用程序注册键盘消息接收通道的过程中的Step 18(InputDispatcher.registerInputChannel)。
这样, 应用程序注销键盘消息接收通道的过程就分析完成了,整个应用程序键盘消息处理机制也分析完成了,这是一个比较复杂的过程,要完全理解它还需要花费一些努力和时间,不过,理解了这个过程之后,对Android应用程序框架层的理解就更进一步了。