InputManagerService分析一:IMS的启动与事件传递

从这一节里面,我们开始介绍InputManagerService部分的知识。它用于管理整个系统的输入部分,包括键盘、鼠标、触摸屏等等。这一章里面我们主要就要介绍IMS。首先从IMS的启动来分析:

[java]  view plain  copy
  1. HandlerThread wmHandlerThread = new HandlerThread("WindowManager");  
  2. wmHandlerThread.start();  
  3. Handler wmHandler = new Handler(wmHandlerThread.getLooper());    
  4.   
  5.     inputManager = new InputManagerService(context, wmHandler);             
  6.     wm = WindowManagerService.main(context, power, display, inputManager,  
  7.             wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,  
  8.             !firstBoot, onlyCore);  
  9.     ServiceManager.addService(Context.WINDOW_SERVICE, wm);  
  10.     ServiceManager.addService(Context.INPUT_SERVICE, inputManager);  
  11.   
  12.     inputManager.setWindowManagerCallbacks(wm.getInputMonitor());  
  13.     inputManager.start();  


因为 在Android系统中,按键事件是由InputManager来收集并由WindowManagerService服务来分发给各个Activity处理的,所以在介绍WMS的启动时,我们也一起来介绍一下InputManager的启动,首先来看InputManagerService的构造函数:

InputManagerService的启动

[java]  view plain  copy
  1. public InputManagerService(Context context, Handler handler) {  
  2.     this.mContext = context;  
  3.     this.mHandler = new InputManagerHandler(handler.getLooper());  
  4.   
  5.     mUseDevInputEventForAudioJack =  
  6.             context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);  
  7.     mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());  
  8. }  
这里首先构造InputManagerHandler用于处理消息,当然这个handle是绑定在"WindowManager"这个looper上的。然后调用nativeInit去完成初natvie层的初始化:
[java]  view plain  copy
  1. static jint nativeInit(JNIEnv* env, jclass clazz,  
  2.         jobject serviceObj, jobject contextObj, jobject messageQueueObj) {  
  3.     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);  
  4.   
  5.     NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,  
  6.             messageQueue->getLooper());  
  7.     im->incStrong(0);  
  8.     return reinterpret_cast<jint>(im);  
  9. }  
android_os_MessageQueue_getMessageQueue这个函数我们在介绍Looper的时候已经分析过,因为Java层的MessageQueue总是对应native层的NativeMessageQueue对象,所以首先先取得native层的messageQueue,并构造NativeInputManager对象:
[java]  view plain  copy
  1. NativeInputManager::NativeInputManager(jobject contextObj,  
  2.         jobject serviceObj, const sp<Looper>& looper) :  
  3.         mLooper(looper) {  
  4.     JNIEnv* env = jniEnv();  
  5.   
  6.     mContextObj = env->NewGlobalRef(contextObj);  
  7.     mServiceObj = env->NewGlobalRef(serviceObj);  
  8.   
  9.     {  
  10.         AutoMutex _l(mLock);  
  11.         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;  
  12.         mLocked.pointerSpeed = 0;  
  13.         mLocked.pointerGesturesEnabled = true;  
  14.         mLocked.showTouches = false;  
  15.     }  
  16.   
  17.     sp<EventHub> eventHub = new EventHub();  
  18.     mInputManager = new InputManager(eventHub, thisthis);  
  19. }  
上面的InputManagerService的NativeInputManager的类图关系如下:



在NativeInputManager的构造函数中,首先对mLocked中的一些变量赋初值。然后构造EventHub对象,并通过它最终构造InputManager对象。首先来看EventHub的构造函数:
[java]  view plain  copy
  1. EventHub::EventHub(void) :  
  2.         mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),  
  3.         mOpeningDevices(0), mClosingDevices(0),  
  4.         mNeedToSendFinishedDeviceScan(false),  
  5.         mNeedToReopenDevices(false), mNeedToScanDevices(true),  
  6.         mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {  
  7.     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);  
  8.   
  9.     mEpollFd = epoll_create(EPOLL_SIZE_HINT);  
  10.     LOG_ALWAYS_FATAL_IF(mEpollFd < 0"Could not create epoll instance.  errno=%d", errno);  
  11.   
  12.     mINotifyFd = inotify_init();  
  13.     int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);  
  14.     LOG_ALWAYS_FATAL_IF(result < 0"Could not register INotify for %s.  errno=%d",  
  15.             DEVICE_PATH, errno);  
  16.   
  17.     struct epoll_event eventItem;  
  18.     memset(&eventItem, 0, sizeof(eventItem));  
  19.     eventItem.events = EPOLLIN;  
  20.     eventItem.data.u32 = EPOLL_ID_INOTIFY;  
  21.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);  
  22.     LOG_ALWAYS_FATAL_IF(result != 0"Could not add INotify to epoll instance.  errno=%d", errno);  
  23.   
  24.     int wakeFds[2];  
  25.     result = pipe(wakeFds);  
  26.     LOG_ALWAYS_FATAL_IF(result != 0"Could not create wake pipe.  errno=%d", errno);  
  27.   
  28.     mWakeReadPipeFd = wakeFds[0];  
  29.     mWakeWritePipeFd = wakeFds[1];  
  30.   
  31.     result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);  
  32.     LOG_ALWAYS_FATAL_IF(result != 0"Could not make wake read pipe non-blocking.  errno=%d",  
  33.             errno);  
  34.   
  35.     result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);  
  36.     LOG_ALWAYS_FATAL_IF(result != 0"Could not make wake write pipe non-blocking.  errno=%d",  
  37.             errno);  
  38.   
  39.     eventItem.data.u32 = EPOLL_ID_WAKE;  
  40.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);  
  41.     LOG_ALWAYS_FATAL_IF(result != 0"Could not add wake read pipe to epoll instance.  errno=%d",  
  42.             errno);  
  43. }  

首先是对一些成员变量做初始化,这些变量等到我们用到时再来一一介绍。然后调用inotify机制对/dev/input文件目录下的增和删操作做监听,/dev/input目录就是所有的input设备文件。并调用epoll机制EPOLL_CTL_ADD命令对上面的inotify的句柄和mWakeReadPipeFd句柄加入到epoll的句柄mEpollFd中。我们可以看到当有/dev/input下面的增删操作或者在mWakeWritePipeFd中写数据时,epoll_wait将会返回。再来看InputManager的构造函数:

[java]  view plain  copy
  1. InputManager::InputManager(  
  2.         const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
  4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
  5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
  6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
  7.     initialize();  
  8. }  
  9.   
  10. void InputManager::initialize() {  
  11.     mReaderThread = new InputReaderThread(mReader);  
  12.     mDispatcherThread = new InputDispatcherThread(mDispatcher);  
  13. }  

这InputManager的构造函数中首先构造InputDispatcher和InputReader两个对象,然后在initialize构造InputReaderThread和InputDispatcherThread分别用于收按键输入和分发按键消息。InputDispatcher是分发消息的对象,InputReader是从驱动获取按键消息,首先来看一下它们的构造函数:

[java]  view plain  copy
  1. InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :  
  2.     mPolicy(policy),  
  3.     mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),  
  4.     mNextUnblockedEvent(NULL),  
  5.     mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),  
  6.     mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {  
  7.     mLooper = new Looper(false);  
  8.   
  9.     mKeyRepeatState.lastKeyEntry = NULL;  
  10.   
  11.     policy->getDispatcherConfiguration(&mConfig);  
  12. }  
InputDispatcher的构造函数中首先初始化一些成员变量,然后构造一个Native层的Looper,并通过IMS获取VirtualKeyQuietime和ExcludedDevice系统配置保存到InputDispatcherConfiguration选项。接着来看InputReader的构造函数:
[java]  view plain  copy
  1. InputReader::InputReader(const sp<EventHubInterface>& eventHub,  
  2.         const sp<InputReaderPolicyInterface>& policy,  
  3.         const sp<InputListenerInterface>& listener) :  
  4.         mContext(this), mEventHub(eventHub), mPolicy(policy),  
  5.         mGlobalMetaState(0), mGeneration(1),  
  6.         mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),  
  7.         mConfigurationChangesToRefresh(0) {  
  8.     mQueuedListener = new QueuedInputListener(listener);  
  9.   
  10.     { // acquire lock  
  11.         AutoMutex _l(mLock);  
  12.   
  13.         refreshConfigurationLocked(0);  
  14.         updateGlobalMetaStateLocked();  
  15.     } // release lock  
  16. }  

这里首先由传入的InputDispatcher构造一个QueuedInputListener并保存在mQueuedListener中。回到InputManager的构造函数中,接着调用initialize构造分别构造InputReaderThread和InputDispatcherThread两个thread。

InputReader和InputDispatcher两个类都比较庞大,我们先来看一下它们的类图:




再来看一下上面IMS构造过程的流程图:




到这里InputManagerService的构造函数就介绍完了,回到SystemService中接着调用WMS的main方法,并把前面创建的InputManagerService作为参数传入:
[java]  view plain  copy
  1. private WindowManagerService(Context context, PowerManagerService pm,  
  2.         DisplayManagerService displayManager, InputManagerService inputManager,  
  3.         boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {  
  4.           
  5.     ......  
  6.       
  7.     mInputManager = inputManager; // Must be before createDisplayContentLocked.  
  8.   
  9.     mPointerEventDispatcher = new PointerEventDispatcher(mInputManager.monitorInput(TAG));  
  10.       
  11.     .....  
  12. }  

在WMS的构造函数中,首先在mInputManager中保存InputManagerService对象,然后构造PointerEventDispatcher对用于分析点击事件。首先来看InputManagerService的monitorInput方法:

[java]  view plain  copy
  1. public InputChannel monitorInput(String inputChannelName) {  
  2.     InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);  
  3.     nativeRegisterInputChannel(mPtr, inputChannels[0], nulltrue);  
  4.     inputChannels[0].dispose(); // don't need to retain the Java object reference  
  5.     return inputChannels[1];  
  6. }  

先来看一下InputChannel的类图结构:




InputChannel用于从InputDispatcher中后去所有的input消息,所以这里构造一对InputChannel,一个注册到底层的InputDispatcher中,一个用于PointerEventDispatcher给activity分发消息。先来看InputChannel的openInputChannelPair函数:
[java]  view plain  copy
  1.     public static InputChannel[] openInputChannelPair(String name) {  
  2.         return nativeOpenInputChannelPair(name);  
  3.     }  
  4.   
  5. static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,  
  6.         jclass clazz, jstring nameObj) {  
  7.     const char* nameChars = env->GetStringUTFChars(nameObj, NULL);  
  8.     String8 name(nameChars);  
  9.     env->ReleaseStringUTFChars(nameObj, nameChars);  
  10.   
  11.     sp<InputChannel> serverChannel;  
  12.     sp<InputChannel> clientChannel;  
  13.     status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);  
  14.   
  15.     if (result) {  
  16.         String8 message;  
  17.         message.appendFormat("Could not open input channel pair.  status=%d", result);  
  18.         jniThrowRuntimeException(env, message.string());  
  19.         return NULL;  
  20.     }  
  21.   
  22.     jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);  
  23.     if (env->ExceptionCheck()) {  
  24.         return NULL;  
  25.     }  
  26.   
  27.     jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,  
  28.             new NativeInputChannel(serverChannel));  
  29.     if (env->ExceptionCheck()) {  
  30.         return NULL;  
  31.     }  
  32.   
  33.     jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,  
  34.             new NativeInputChannel(clientChannel));  
  35.     if (env->ExceptionCheck()) {  
  36.         return NULL;  
  37.     }  
  38.   
  39.     env->SetObjectArrayElement(channelPair, 0, serverChannelObj);  
  40.     env->SetObjectArrayElement(channelPair, 1, clientChannelObj);  
  41.     return channelPair;  
  42. }  

android_view_InputChannel_nativeOpenInputChannelPair函数首先调用Native层的InputChannel的openInputChannelPair函数创建一对socket,先来看openInputChannelPair的实现:
[cpp]  view plain  copy
  1. status_t InputChannel::openInputChannelPair(const String8& name,  
  2.         sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {  
  3.     int sockets[2];  
  4.     if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {  
  5.         status_t result = -errno;  
  6.         ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d",  
  7.                 name.string(), errno);  
  8.         outServerChannel.clear();  
  9.         outClientChannel.clear();  
  10.         return result;  
  11.     }  
  12.   
  13.     int bufferSize = SOCKET_BUFFER_SIZE;  
  14.     setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));  
  15.     setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));  
  16.     setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));  
  17.     setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));  
  18.   
  19.     String8 serverChannelName = name;  
  20.     serverChannelName.append(" (server)");  
  21.     outServerChannel = new InputChannel(serverChannelName, sockets[0]);  
  22.   
  23.     String8 clientChannelName = name;  
  24.     clientChannelName.append(" (client)");  
  25.     outClientChannel = new InputChannel(clientChannelName, sockets[1]);  
  26.     return OK;  
  27. }  
上面的代码比较简单,首先创建一对未命名、相互连接的UNIX域套接字,然后分别通过Fd分别构造两个Native层的InputChannel代表server和client端。在android_view_InputChannel_nativeOpenInputChannelPair函数中把Native层的InputChannel和Java层的InputChannel通过NativeInputChannel相互绑定起来。

回到InputManagerService的monitorInput方法中,InputChannel的openInputChannelPair返回一对InputChannel对象,其中index为0的代表server端,index为1的代表client端。接着调用nativeRegisterInputChannel把InputChannel[0]到InputDispatcher,用于从InputDispatcher获取触摸事件:

[cpp]  view plain  copy
  1. static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,  
  2.         jint ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {  
  3.     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  
  4.   
  5.     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,  
  6.             inputChannelObj);  
  7.     if (inputChannel == NULL) {  
  8.         throwInputChannelNotInitialized(env);  
  9.         return;  
  10.     }  
  11.   
  12.     sp<InputWindowHandle> inputWindowHandle =  
  13.             android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);  
  14.   
  15.     status_t status = im->registerInputChannel(  
  16.             env, inputChannel, inputWindowHandle, monitor);  
  17.     if (status) {  
  18.     }  
  19. }  
  20.   
  21. status_t NativeInputManager::registerInputChannel(JNIEnv* env,  
  22.         const sp<InputChannel>& inputChannel,  
  23.         const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {  
  24.     return mInputManager->getDispatcher()->registerInputChannel(  
  25.             inputChannel, inputWindowHandle, monitor);  
  26. }  
nativeRegisterInputChannel首先通过Java层的InputChannel对象获取到Native层的InputChannel对象,然后调用NativeInputManager的registerInputChannel方法,因为当前没有设置inputWindowhandler,所以这里的InputWindowHandler为NULL:

[cpp]  view plain  copy
  1. status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,  
  2.         const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {  
  3.     { // acquire lock  
  4.         AutoMutex _l(mLock);  
  5.   
  6.         if (getConnectionIndexLocked(inputChannel) >= 0) {  
  7.             ALOGW("Attempted to register already registered input channel '%s'",  
  8.                     inputChannel->getName().string());  
  9.             return BAD_VALUE;  
  10.         }  
  11.   
  12.         sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);  
  13.   
  14.         int fd = inputChannel->getFd();  
  15.         mConnectionsByFd.add(fd, connection);  
  16.   
  17.         if (monitor) {  
  18.             mMonitoringChannels.push(inputChannel);  
  19.         }  
  20.   
  21.         mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);  
  22.     } // release lock  
  23.   
  24.     // Wake the looper because some connections have changed.  
  25.             return BAD_VALUE;  
  26.         }  
  27.   
  28.         sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);  
  29.   
  30.         int fd = inputChannel->getFd();  
  31.         mConnectionsByFd.add(fd, connection);  
  32.   
  33.         if (monitor) {  
  34.             mMonitoringChannels.push(inputChannel);  
  35.         }  
  36.   
  37.         mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);  
  38.     } // release lock  
  39.   
  40.     // Wake the looper because some connections have changed.  
  41.     mLooper->wake();  
  42.     return OK;  
相关文章
相关标签/搜索