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.     mLooper->wake();  
  26.     return OK;  
  27. }  
registerInputChannel首先构造Connection对象表示一个连接,然后把它加入到mConnectionsByFd中,并根据当前inputChannel是否需要monitor加入到mMonitoringChannels,并最终把inputChannel所代表的fd值加入到Looper的mEpollFd中。

最后因为在Java层不再需要Native层的inputChannels[0]引用,所以调用inputChannels[0]的dispose方法用于释放Java层对Native层的inputChannels[0]的引用。最后来看WMS中的PointerEventDispatcher构造函数:

[java]  view plain  copy
  1. public PointerEventDispatcher(InputChannel inputChannel) {  
  2.     super(inputChannel, UiThread.getHandler().getLooper());  
  3. }  
  4.   
  5. public InputEventReceiver(InputChannel inputChannel, Looper looper) {  
  6.     if (inputChannel == null) {  
  7.         throw new IllegalArgumentException("inputChannel must not be null");  
  8.     }  
  9.     if (looper == null) {  
  10.         throw new IllegalArgumentException("looper must not be null");  
  11.     }  
  12.   
  13.     mInputChannel = inputChannel;  
  14.     mMessageQueue = looper.getQueue();  
  15.     mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),  
  16.             inputChannel, mMessageQueue);  
  17.   
  18.     mCloseGuard.open("dispose");  
  19. }  

传入的参数为前面创造的inputChannel[1];UiThread为管理UI的一个单例Thread。这里主要调用nativeInit方法:

[java]  view plain  copy
  1. static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,  
  2.         jobject inputChannelObj, jobject messageQueueObj) {  
  3.     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,  
  4.             inputChannelObj);  
  5.     if (inputChannel == NULL) {  
  6.         jniThrowRuntimeException(env, "InputChannel is not initialized.");  
  7.         return 0;  
  8.     }  
  9.   
  10.     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);  
  11.     if (messageQueue == NULL) {  
  12.         jniThrowRuntimeException(env, "MessageQueue is not initialized.");  
  13.         return 0;  
  14.     }  
  15.   
  16.     sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,  
  17.             receiverWeak, inputChannel, messageQueue);  
  18.     status_t status = receiver->initialize();  
  19.     if (status) {  
  20.   
  21.     }  
  22.   
  23.     receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object  
  24.     return reinterpret_cast<jint>(receiver.get());  
  25. }  
nativeInit函数首先获取Java层传入的InputChannel和MessageQueue对象,然后构造NativeInputEventReceiver对象并调用它的initialize方法将InputChannel[1]与UiThread的looper绑定起来:

[cpp]  view plain  copy
  1. NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,  
  2.         jobject receiverWeak, const sp<InputChannel>& inputChannel,  
  3.         const sp<MessageQueue>& messageQueue) :  
  4.         mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),  
  5.         mInputConsumer(inputChannel), mMessageQueue(messageQueue),  
  6.         mBatchedInputEventPending(false), mFdEvents(0) {  
  7. }  
  8.   
  9. status_t NativeInputEventReceiver::initialize() {  
  10.     setFdEvents(ALOOPER_EVENT_INPUT);  
  11.     return OK;  
  12. }  
  13.   
  14. void NativeInputEventReceiver::setFdEvents(int events) {  
  15.     if (mFdEvents != events) {  
  16.         mFdEvents = events;  
  17.         int fd = mInputConsumer.getChannel()->getFd();  
  18.         if (events) {  
  19.             mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);  
  20.         } else {  
  21.             mMessageQueue->getLooper()->removeFd(fd);  
  22.         }  
  23.     }  
  24. }  
下面是以上介绍PointerEventDispatcher注册InputChannel到InputDispatch的流程图:



回到systemServer当中,接着调用inputManager.setWindowManagerCallbacks(wm.getInputMonitor())方法用于想WMS通知InputManager的状态变化以及错误通知。最后在systemServer中调用inputManager.start()方法让InputManagerService启动:

[java]  view plain  copy
  1. public void start() {  
  2.     Slog.i(TAG, "Starting input manager");  
  3.     nativeStart(mPtr);  
  4.   
  5.     // Add ourself to the Watchdog monitors.  
  6.     Watchdog.getInstance().addMonitor(this);  
  7.   
  8.     registerPointerSpeedSettingObserver();  
  9.     registerShowTouchesSettingObserver();  
  10.   
  11.     mContext.registerReceiver(new BroadcastReceiver() {  
  12.         @Override  
  13.         public void onReceive(Context context, Intent intent) {  
  14.             updatePointerSpeedFromSettings();  
  15.             updateShowTouchesFromSettings();  
  16.         }  
  17.     }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);  
  18.   
  19.     updatePointerSpeedFromSettings();  
  20.     updateShowTouchesFromSettings();  
  21. }  

首先调用nativeStart让Native层的InputManager启动:

[cpp]  view plain  copy
  1. status_t InputManager::start() {  
  2.     status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  
  3.     if (result) {  
  4.         ALOGE("Could not start InputDispatcher thread due to error %d.", result);  
  5.         return result;  
  6.     }  
  7.   
  8.     result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);  
  9.     if (result) {  
  10.         ALOGE("Could not start InputReader thread due to error %d.", result);  
  11.   
  12.         mDispatcherThread->requestExit();  
  13.         return result;  
  14.     }  
  15.   
  16.     return OK;  
  17. }  

InputManager的start方法让在initialize函数中创建的两个thread跑起来,我们首先来看InputDispatcherThread的threadLoop方法:

[cpp]  view plain  copy
  1. bool InputDispatcherThread::threadLoop() {  
  2.     mDispatcher->dispatchOnce();  
  3.     return true;  
  4. }  
  5.   
  6. void InputDispatcher::dispatchOnce() {  
  7.     nsecs_t nextWakeupTime = LONG_LONG_MAX;  
  8.     { // acquire lock  
  9.         AutoMutex _l(mLock);  
  10.         mDispatcherIsAliveCondition.broadcast();  
  11.   
  12.         // Run a dispatch loop if there are no pending commands.  
  13.         // The dispatch loop might enqueue commands to run afterwards.  
  14.         if (!haveCommandsLocked()) {  
  15.             dispatchOnceInnerLocked(&nextWakeupTime);  
  16.         }  
  17.   
  18.         // Run all pending commands if there are any.  
  19.         // If any commands were run then force the next poll to wake up immediately.  
  20.         if (runCommandsLockedInterruptible()) {  
  21.             nextWakeupTime = LONG_LONG_MIN;  
  22.         }  
  23.     } // release lock  
  24.   
  25.     // Wait for callback or timeout or wake.  (make sure we round up, not down)  
  26.     nsecs_t currentTime = now();  
  27.     int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);  
  28.     mLooper->pollOnce(timeoutMillis);  
  29. }  

dispatchOnce处理函数中,首先检查是否有缓存的命令未执行,如果有,就先执行这些命令;如果没有,就调用dispatchOnceInnerLocked方法去检查是否有新的input事件发生,如果有则分发,我们后面再来分析dispatchOnceInnerLocked函数。这里是第一次启动,所以InputDispatcherThread的threadLoop方法调用Looper的pollOnce陷入等待。

接着在InputManager的start方法中启动InputReaderThread:

[cpp]  view plain  copy
  1. bool InputReaderThread::threadLoop() {  
  2.     mReader->loopOnce();  
  3.     return true;  
  4. }  
  5.   
  6. void InputReader::loopOnce() {  
  7.     int32_t oldGeneration;  
  8.     int32_t timeoutMillis;  
  9.     bool inputDevicesChanged = false;  
  10.     Vector<InputDeviceInfo> inputDevices;  
  11.     { // acquire lock  
  12.         AutoMutex _l(mLock);  
  13.   
  14.         oldGeneration = mGeneration;  
  15.         timeoutMillis = -1;  
  16.   
  17.         uint32_t changes = mConfigurationChangesToRefresh;  
  18.         if (changes) {  
  19.             mConfigurationChangesToRefresh = 0;  
  20.             timeoutMillis = 0;  
  21.             refreshConfigurationLocked(changes);  
  22.         } else if (mNextTimeout != LLONG_MAX) {  
  23.             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  24.             timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);  
  25.         }  
  26.     } // release lock  
  27.   
  28.     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  
  29.   
  30.     { // acquire lock  
  31.         AutoMutex _l(mLock);  
  32.         mReaderIsAliveCondition.broadcast();  
  33.   
  34.         if (count) {  
  35.             processEventsLocked(mEventBuffer, count);  
  36.         }  
  37.   
  38.         if (mNextTimeout != LLONG_MAX) {  
  39.             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  40.             if (now >= mNextTimeout) {  
  41. #if DEBUG_RAW_EVENTS  
  42.                 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);  
  43. #endif  
  44.                 mNextTimeout = LLONG_MAX;  
  45.                 timeoutExpiredLocked(now);  
  46.             }  
  47.         }  
  48.   
  49.         if (oldGeneration != mGeneration) {  
  50.             inputDevicesChanged = true;  
  51.             getInputDevicesLocked(inputDevices);  
  52.         }  
  53.     } // release lock  
  54.   
  55.     // Send out a message that the describes the changed input devices.  
  56.     if (inputDevicesChanged) {  
  57.         mPolicy->notifyInputDevicesChanged(inputDevices);  
  58.     }  
  59.   
  60.     mQueuedListener->flush();  
  61. }  
InputReader的loopOnce方法调用EventHub的getEvents方法获取一个input事件,并保存在RawEvent数组中,如果RawEvent事件的数目大于0,则调用processEventsLocked去处理这些事件。我们先来看EventHub的getEvents方法,这个函数比较长,我们分段来分析:

[cpp]  view plain  copy
  1. size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {  
  2.     ALOG_ASSERT(bufferSize >= 1);  
  3.   
  4.     AutoMutex _l(mLock);  
  5.   
  6.     struct input_event readBuffer[bufferSize];  
  7.   
  8.     RawEvent* event = buffer;  
  9.     size_t capacity = bufferSize;  
  10.     bool awoken = false;  
  11.     for (;;) {  
  12.         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  13.   
  14.         // 重新reopen所有的input device  
  15.         if (mNeedToReopenDevices) {  
  16.   
  17.         }  
  18.   
  19.         // 处理要关闭的input device  
  20.         while (mClosingDevices) {  
  21.   
  22.         }  
  23.   
  24.         if (mNeedToScanDevices) {  
  25.             mNeedToScanDevices = false;  
  26.             scanDevicesLocked();  
  27.             mNeedToSendFinishedDeviceScan = true;  
  28.         }  

在getEvents函数中,首先检查是否要重新reopen所有的input device设备,然后检查是否有待关闭的input设备。如果这是第一次调用getEvents函数,则需要调用scanDevicesLocked函数去扫描/dev/input目录下的设备文件并打开这些设备:

[cpp]  view plain  copy
  1. void EventHub::scanDevicesLocked() {  
  2.     status_t res = scanDirLocked(DEVICE_PATH);  
  3.     if(res < 0) {  
  4.         ALOGE("scan dir failed for %s\n", DEVICE_PATH);  
  5.     }  
  6.     if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {  
  7.         createVirtualKeyboardLocked();  
  8.     }  
  9. }  
  10.   
  11. status_t EventHub::scanDirLocked(const char *dirname)  
  12. {  
  13.     char devname[PATH_MAX];  
  14.     char *filename;  
  15.     DIR *dir;  
  16.     struct dirent *de;  
  17.     dir = opendir(dirname);  
  18.     if(dir == NULL)  
  19.         return -1;  
  20.     strcpy(devname, dirname);  
  21.     filename = devname + strlen(devname);  
  22.     *filename++ = '/';  
  23.     while((de = readdir(dir))) {  
  24.         if(de->d_name[0] == '.' &&  
  25.            (de->d_name[1] == '\0' ||  
  26.             (de->d_name[1] == '.' && de->d_name[2] == '\0')))  
  27.             continue;  
  28.         strcpy(filename, de->d_name);  
  29.         openDeviceLocked(devname);  
  30.     }  
  31.     closedir(dir);  
  32.     return 0;  
  33. }  

scanDirLocked函数依次调用openDeviceLocked函数去打开/dev/input下面的文件:

[cpp]  view plain  copy
  1. status_t EventHub::openDeviceLocked(const char *devicePath) {  
  2.     char buffer[80];  
  3.   
  4.     ALOGV("Opening device: %s", devicePath);  
  5.   
  6.     int fd = open(devicePath, O_RDWR | O_CLOEXEC);  
  7.     if(fd < 0) {  
  8.         ALOGE("could not open %s, %s\n", devicePath, strerror(errno));  
  9.         return -1;  
  10.     }  
  11.   
  12.     InputDeviceIdentifier identifier;  
  13.   
  14.     // Get device name.  
  15.     if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {  
  16.   
  17.     } else {  
  18.         buffer[sizeof(buffer) - 1] = '\0';  
  19.         identifier.name.setTo(buffer);  
  20.     }  
  21.   
  22.     // Check to see if the device is on our excluded list  
  23.     for (size_t i = 0; i < mExcludedDevices.size(); i++) {  
  24.         const String8& item = mExcludedDevices.itemAt(i);  
  25.         if (identifier.name == item) {  
  26.   
  27.         }  
  28.     }  
  29.   
  30.     // Get device driver version.  
  31.     int driverVersion;  
  32.     if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {  
  33.     }  
  34.   
  35.     // Get device identifier.  
  36.     struct input_id inputId;  
  37.     if(ioctl(fd, EVIOCGID, &inputId)) {  
  38.     }  
  39.     identifier.bus = inputId.bustype;  
  40.     identifier.product = inputId.product;  
  41.     identifier.vendor = inputId.vendor;  
  42.     identifier.version = inputId.version;  
  43.   
  44.     // Get device physical location.  
  45.     if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {  
  46.       
  47.     } else {  
  48.         buffer[sizeof(buffer) - 1] = '\0';  
  49.         identifier.location.setTo(buffer);  
  50.     }  
  51.   
  52.     // Get device unique id.  
  53.     if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {  
  54.   
  55.     } else {  
  56.         buffer[sizeof(buffer) - 1] = '\0';  
  57.         identifier.uniqueId.setTo(buffer);  
  58.     }  
  59.   
  60.     // Fill in the descriptor.  
  61.     setDescriptor(identifier);  
  62.   
  63.     // Make file descriptor non-blocking for use with poll().  
  64.     if (fcntl(fd, F_SETFL, O_NONBLOCK)) {  
  65.   
  66.     }  
  67.   
  68.     int32_t deviceId = mNextDeviceId++;  
  69.     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);  
  70.   
  71.     // Load the configuration file for the device.  
  72.     loadConfigurationLocked(device);  
  73.   
  74.     .......  
  75.       
  76.     if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {  
  77.         status_t status = loadVirtualKeyMapLocked(device);  
  78.         if (!status) {  
  79.             device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;  
  80.         }  
  81.     }  
  82.     status_t keyMapStatus = NAME_NOT_FOUND;  
  83.     if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {  
  84.         // Load the keymap for the device.  
  85.         keyMapStatus = loadKeyMapLocked(device);  
  86.     }  
  87.   
  88.     // Register with epoll.  
  89.     struct epoll_event eventItem;  
  90.     memset(&eventItem, 0, sizeof(eventItem));  
  91.     eventItem.events = EPOLLIN;  
  92.     eventItem.data.u32 = deviceId;  
  93.     if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {  
  94.         ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);  
  95.         delete device;  
  96.         return -1;  
  97.     }  
  98.   
  99.     bool usingSuspendBlockIoctl = !ioctl(fd, EVIOCSSUSPENDBLOCK, 1);  
  100.   
  101.     int clockId = CLOCK_MONOTONIC;  
  102.     bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);  
  103.   
  104.     addDeviceLocked(device);  
  105.     return 0;  
  106. }  

首先打开/dev/input/**文件,然后通过ioctl获取这个input设备的信息,并构造一个Device对象来表示它。然后调用loadConfigurationLocked去加载这个设备的 idc(Input Device Configuration)配置文件(一般情况下会不存在idc文件),查找idc文件的顺序是:

/system/usr/idc/Vendor_XXXX_Product_XXXX_Version_XXXX.idc
/data/system/devices/idc / Vendor_XXXX_Product_XXXX_Version_XXXX.idc
/system/usr/idc/Vendor_XXXX_Product_XXXX.idc
/data/system/devices/idc/Vendor_XXXX_Product_XXXX.idc
/system/usr/idc/Device_Name.idc
/data/system/devices/idc/Device_Name.idc

如果在上面的目录中找到对象的idc文件,则调用PropertyMap将它加载并保存在Device的configuration成员中。接着在openDeviceLocked根据input设备的不同类型分别调用不同的case来加载设备相关的文件:例如对于touch设备,调用loadVirtualKeyMapLocked去加载虚拟keyMap;对于keyboard调用loadKeyMapLocked函数加载它的keyMap,这里调用KeyMapd对象的load方法去加载:

[cpp]  view plain  copy
  1. status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier,  
  2.         const PropertyMap* deviceConfiguration) {  
  3.     if (deviceConfiguration) {  
  4.   
  5.     }  
  6.   
  7.     // Try searching by device identifier.  
  8.     if (probeKeyMap(deviceIdenfifier, String8::empty())) {  
  9.         return OK;  
  10.     }  
  11.   
  12.     // Fall back on the Generic key map.  
  13.     // TODO Apply some additional heuristics here to figure out what kind of  
  14.     //      generic key map to use (US English, etc.) for typical external keyboards.  
  15.     if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {  
  16.         return OK;  
  17.     }  
  18.   
  19.     // Try the Virtual key map as a last resort.  
  20.     if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {  
  21.         return OK;  
  22.     }  
  23.   
  24.     // Give up!  
  25.     ALOGE("Could not determine key map for device '%s' and no default key maps were found!",  
  26.             deviceIdenfifier.name.string());  
  27.     return NAME_NOT_FOUND;  
  28. }  

在load函数中,首先尝试使用idc文件中的"keyboard.layout"和"keyboard.characterMap"两个选项去加载keyboard的layout和characterMap文件。如果没有idc文件,则调用probeKeyMap函数分别从下面几个目录查找keyboard的layout和characterMap文件,查找layout文件的顺序如下:

/system/usr/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX_Version_XXXX.kl
/system/usr/keylayout/Vendor_XXXX_Product_XXXX.kl
/data/system/devices/keylayout/Vendor_XXXX_Product_XXXX.kl
/system/usr/keylayout/DEVICE_NAME.kl
/data/system/devices/keylayout/DEVICE_NAME.kl
/system/usr/keylayout/Generic.kl
/data/system/devices/keylayout/Generic.kl
/system/usr/keylayout/Virtual.kl
/data/system/devices/keylayout/Virtual.kl

查找characterMap文件的顺序如下:

/system/usr/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX_Version_XXXX.kcm
/system/usr/keychars/Vendor_XXXX_Product_XXXX.kcm
/data/system/devices/keychars/Vendor_XXXX_Product_XXXX.kcm
/system/usr/keychars/DEVICE_NAME.kcm
/data/system/devices/keychars/DEVICE_NAME.kcm
/system/usr/keychars/Generic.kcm
/data/system/devices/keychars/Generic.kcm
/system/usr/keychars/Virtual.kcm
/data/system/devices/keychars/Virtual.kcm

其中,*.kl文件用于描述Linux scan code到 按键的标签的映射关系;*.kcm文件用于描述在shift、caps lock、ctrl以及alt同时按下时的关系。回到openDeviceLocked函数中,通过epoll_ctl把刚打开的input设备的fd加入到mEpollFd中,用于在epoll_wait中等待对应input设备的事件发生。最后调用addDeviceLocked将Device对象加入到mDevices数组和mOpeningDevices中:
[cpp]  view plain  copy
  1. void EventHub::addDeviceLocked(Device* device) {  
  2.     mDevices.add(device->id, device);  
  3.     device->next = mOpeningDevices;  
  4.     mOpeningDevices = device;  
  5. }  

接着来看scanDevicesLocked函数中,mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID)这句代码用于判断当前设备列表中是否存在虚拟键盘,如果不存在,则调用createVirtualKeyboardLocked去创建一个:

[cpp]  view plain  copy
  1. void EventHub::createVirtualKeyboardLocked() {  
  2.     InputDeviceIdentifier identifier;  
  3.     identifier.name = "Virtual";  
  4.     identifier.uniqueId = "<virtual>";  
  5.     setDescriptor(identifier);  
  6.   
  7.     Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier);  
  8.     device->classes = INPUT_DEVICE_CLASS_KEYBOARD  
  9.             | INPUT_DEVICE_CLASS_ALPHAKEY  
  10.             | INPUT_DEVICE_CLASS_DPAD  
  11.             | INPUT_DEVICE_CLASS_VIRTUAL;  
  12.     loadKeyMapLocked(device);  
  13.     addDeviceLocked(device);  
  14. }  

这时回到getEvents函数中,mDevices和 mOpeningDevices至少存在两个input设备了,一个是触摸屏,另一个是虚拟键盘。接着往下看getEvents函数:

[cpp]  view plain  copy
  1.         while (mOpeningDevices != NULL) {  
  2.             Device* device = mOpeningDevices;  
  3.             ALOGV("Reporting device opened: id=%d, name=%s\n",  
  4.                  device->id, device->path.string());  
  5.             mOpeningDevices = device->next;  
  6.             event->when = now;  
  7.             event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;  
  8.             event->type = DEVICE_ADDED;  
  9.             event += 1;  
  10.             mNeedToSendFinishedDeviceScan = true;  
  11.             if (--capacity == 0) {  
  12.                 break;  
  13.             }  
  14.         }  
  15.   
  16.         if (mNeedToSendFinishedDeviceScan) {  
  17.             mNeedToSendFinishedDeviceScan = false;  
  18.             event->when = now;  
  19.             event->type = FINISHED_DEVICE_SCAN;  
  20.             event += 1;  
  21.             if (--capacity == 0) {  
  22.                 break;  
  23.             }  
  24.         }  
  25.   
  26.         // Grab the next input event.  
  27.         bool deviceChanged = false;  
  28.         while (mPendingEventIndex < mPendingEventCount) {  
  29.             const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];  
  30.             if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {  
  31.                 if (eventItem.events & EPOLLIN) {  //在/dev/input目录下有delete、add的inotify  
  32.                     mPendingINotify = true;  
  33.                 } else {  
  34.                 }  
  35.                 continue;  
  36.             }  
  37.   
  38.             if (eventItem.data.u32 == EPOLL_ID_WAKE) {  
  39.                 if (eventItem.events & EPOLLIN) {  
  40.                     ALOGV("awoken after wake()");  
  41.                     awoken = true;  
  42.                     char buffer[16];  
  43.                     ssize_t nRead;  
  44.                     do {  
  45.                         nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));  
  46.                     } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));  
  47.                 } else {  
  48.                     ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",  
  49.                             eventItem.events);  
  50.                 }  
  51.                 continue;  
  52.             }  
  53.   
  54.             ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);  
  55.             if (deviceIndex < 0) {  
  56.   
  57.             }  
  58.   
  59.             Device* device = mDevices.valueAt(deviceIndex);  
  60.             if (eventItem.events & EPOLLIN) {  
  61.                 int32_t readSize = read(device->fd, readBuffer,  
  62.                         sizeof(struct input_event) * capacity);  
  63.                 if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {  
  64.   
  65.                 } else if (readSize < 0) {  
  66.     
  67.                 } else if ((readSize % sizeof(struct input_event)) != 0) {  
  68.                     ALOGE("could not get event (wrong size: %d)", readSize);  
  69.                 } else {  
  70.                     int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;  
  71.   
  72.                     size_t count = size_t(readSize) / sizeof(struct input_event);  
  73.                     for (size_t i = 0; i < count; i++) {  
  74.                         struct input_event& iev = readBuffer[i];  
  75.                         if (iev.type == EV_MSC) {  
  76.                             if (iev.code == MSC_ANDROID_TIME_SEC) {  
  77.                                 device->timestampOverrideSec = iev.value;  
  78.                                 continue;  
  79.                             } else if (iev.code == MSC_ANDROID_TIME_USEC) {  
  80.                                 device->timestampOverrideUsec = iev.value;  
  81.                                 continue;  
  82.                             }  
  83.                         }  
  84.                         if (device->timestampOverrideSec || device->timestampOverrideUsec) {  
  85.                             iev.time.tv_sec = device->timestampOverrideSec;  
  86.                             iev.time.tv_usec = device->timestampOverrideUsec;  
  87.                             if (iev.type == EV_SYN && iev.code == SYN_REPORT) {  
  88.                                 device->timestampOverrideSec = 0;  
  89.                                 device->timestampOverrideUsec = 0;  
  90.                             }  
  91.                             ALOGV("applied override time %d.%06d",  
  92.                                     int(iev.time.tv_sec), int(iev.time.tv_usec));  
  93.                         }  
  94.   
  95. #ifdef HAVE_POSIX_CLOCKS  
  96.   
  97. #else  
  98.                         event->when = now;  
  99. #endif  
  100.                         event->deviceId = deviceId;  
  101.                         event->type = iev.type;  
  102.                         event->code = iev.code;  
  103.                         event->value = iev.value;  
  104.                         event += 1;  
  105.                         capacity -= 1;  
  106.                     }  
  107.                     if (capacity == 0) {  
  108.                         mPendingEventIndex -= 1;  
  109.                         break;  
  110.                     }  
  111.                 }  
  112.             } else if (eventItem.events & EPOLLHUP) {  
  113.   
  114.             }  
  115.         }  
  116.   
  117.         //处理/dev/input目录下有delete、add的inotify  
  118.         if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {  
  119.             mPendingINotify = false;  
  120.             readNotifyLocked();  
  121.             deviceChanged = true;  
  122.         }  
  123.   
  124.         if (deviceChanged) {  
  125.             continue;  
  126.         }  
  127.   
  128.         if (event != buffer || awoken) {  
  129.             break;  
  130.         }  
  131.   
  132.         mPendingEventIndex = 0;  
  133.   
  134.         mLock.unlock(); // release lock before poll, must be before release_wake_lock  
  135.         release_wake_lock(WAKE_LOCK_ID);  
  136.   
  137.         int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);  
  138.   
  139.         acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);  
  140.         mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock  
  141.   
  142.         if (pollResult == 0) {  
  143.             // Timed out.  
  144.             mPendingEventCount = 0;  
  145.             break;  
  146.         }  
  147.   
  148.         if (pollResult < 0) {  
  149.   
  150.         } else {  
  151.             mPendingEventCount = size_t(pollResult);  
  152.         }  
  153.     }  
  154.   
  155.     return event - buffer;  
  156. }  

在getEvent的方法中,首先将前面打开的input设备信息添加到RawEvent的buffer当中,并置type是DEVICE_ADDED。然后在RawEvent的buffer的末尾添加type为FINISHED_DEVICE_SCAN的event。因为当前还没有调用epoll_wait等待input事件,所以这里先跳过 while (mPendingEventIndex < mPendingEventCount)这个循环,直接把前面两个DEVICE_ADDED的event和FINISHED_DEVICE_SCAN的event返回给InputReader的loopOnce()方法,它会调用processEventsLocked去处理这些RawEvent:
[cpp]  view plain  copy
  1. void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {  
  2.     for (const RawEvent* rawEvent = rawEvents; count;) {  
  3.         int32_t type = rawEvent->type;  
  4.         size_t batchSize = 1;  
  5.         if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {  
  6.   
  7.         } else {  
  8.             switch (rawEvent->type) {  
  9.             case EventHubInterface::DEVICE_ADDED:  
  10.                 addDeviceLocked(rawEvent->when, rawEvent->deviceId);  
  11.                 break;  
  12.             case EventHubInterface::DEVICE_REMOVED:  
  13.                 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);  
  14.                 break;  
  15.             case EventHubInterface::FINISHED_DEVICE_SCAN:  
  16.                 handleConfigurationChangedLocked(rawEvent->when);  
  17.                 break;  
  18.             default:  
  19.                 ALOG_ASSERT(false); // can't happen  
  20.                 break;  
  21.             }  
  22.         }  
  23.         count -= batchSize;  
  24.         rawEvent += batchSize;  
  25.     }  
  26. }  

首先来看addDeviceLocked函数:
[cpp]  view plain  copy
  1. void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {  
  2.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  
  3.     if (deviceIndex >= 0) {  
  4.         ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);  
  5.         return;  
  6.     }  
  7.   
  8.     InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);  
  9.     uint32_t classes = mEventHub->getDeviceClasses(deviceId);  
  10.     int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);  
  11.   
  12.     InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);  
  13.     device->configure(when, &mConfig, 0);  
  14.     device->reset(when);  
  15.   
  16.     if (device->isIgnored()) {  
  17.         ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,  
  18.                 identifier.name.string());  
  19.     } else {  
  20.         ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,  
  21.                 identifier.name.string(), device->getSources());  
  22.     }  
  23.   
  24.     mDevices.add(deviceId, device);  
  25.     bumpGenerationLocked();  
  26. }  

首先通过mEventHub的获取deviceId所对应的InputDeviceIdentifier、classes、controllerNumber信息,然后调用createDeviceLocked方法构造一个InputDevice对象代表一个input设备:
[cpp]  view plain  copy
  1. InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,  
  2.         const InputDeviceIdentifier& identifier, uint32_t classes) {  
  3.     InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),  
  4.             controllerNumber, identifier, classes);  
  5.   
  6.     // External devices.  
  7.     if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {  
  8.         device->setExternal(true);  
  9.     }  
  10.   
  11.     // Switch-like devices.  
  12.     if (classes & INPUT_DEVICE_CLASS_SWITCH) {  
  13.         device->addMapper(new SwitchInputMapper(device));  
  14.     }  
  15.   
  16.     // Vibrator-like devices.  
  17.     if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {  
  18.         device->addMapper(new VibratorInputMapper(device));  
  19.     }  
  20.   
  21.     // Keyboard-like devices.  
  22.     uint32_t keyboardSource = 0;  
  23.     int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;  
  24.     if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {  
  25.         keyboardSource |= AINPUT_SOURCE_KEYBOARD;  
  26.     }  
  27.     if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {  
  28.         keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;  
  29.     }  
  30.     if (classes & INPUT_DEVICE_CLASS_DPAD) {  
  31.         keyboardSource |= AINPUT_SOURCE_DPAD;  
  32.     }  
  33.     if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {  
  34.         keyboardSource |= AINPUT_SOURCE_GAMEPAD;  
  35.     }  
  36.   
  37.     if (keyboardSource != 0) {  
  38.         device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));  
  39.     }  
  40.   
  41.     // Cursor-like devices.  
  42.     if (classes & INPUT_DEVICE_CLASS_CURSOR) {  
  43.         device->addMapper(new CursorInputMapper(device));  
  44.     }  
  45.   
  46.     // Touchscreens and touchpad devices.  
  47.     if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {  
  48.         device->addMapper(new MultiTouchInputMapper(device));  
  49.     } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {  
  50.         device->addMapper(new SingleTouchInputMapper(device));  
  51.     }  
  52.   
  53.     // Joystick-like devices.  
  54.     if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {  
  55.         device->addMapper(new JoystickInputMapper(device));  
  56.     }  
  57.   
  58.     return device;  
  59. }  

createDeviceLocked方法中首先创建一个InputDevice对象,然后根据input设备的不同属性设置不同的Mapper事件转换器,我们以virtual keyboard和触摸屏为例来分析。首先在virtual keyboard的属性为INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY | INPUT_DEVICE_CLASS_DPAD | INPUT_DEVICE_CLASS_VIRTUAL,通过上面的代码,我们知道会调用device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType))会构建一个 KeyboardInputMapper对象并设置到InputDevice的mMappers成员中,这里的keyboardSource为AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_DPAD,keyboardType为AINPUT_KEYBOARD_TYPE_ALPHABETIC:
[cpp]  view plain  copy
  1. KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,  
  2.         uint32_t source, int32_t keyboardType) :  
  3.         InputMapper(device), mSource(source),  
  4.         mKeyboardType(keyboardType) {  
  5. }  

触摸屏的属性为INPUT_DEVICE_CLASS_TOUCH_MT | INPUT_DEVICE_CLASS_TOUCH,所以会调用到device->addMapper(new MultiTouchInputMapper(device))去构建一个MultiTouchInputMapper对象并设置到InputDevice的mMappers成员中。
mapper转换器是有它的继承关系的,我们先来看一下它的关系图,后面在介绍处理InputEvent的时候再来仔细分析每个mapper的process方法:




回到addDeviceLocked函数中,接着调用InputDevice的configure和reset方法,并最终把创建的InputDevice添加到mDevices列表中,并增加mGeneration计数。首先来看InputDevice的configure函数:

[cpp]  view plain  copy
  1. void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {  
  2.     mSources = 0;  
  3.   
  4.     if (!isIgnored()) {  
  5.         if (!changes) { // first time only  
  6.             mContext->getEventHub()->getConfiguration(mId, &mConfiguration);  
  7.         }  
  8.   
  9.         if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {  
  10.             if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {  
  11.                 sp<KeyCharacterMap> keyboardLayout =  
  12.                         mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier.descriptor);  
  13.                 if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {  
  14.                     bumpGeneration();  
  15.                 }  
  16.             }  
  17.         }  
  18.   
  19.         if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {  
  20.             if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {  
  21.                 String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);  
  22.                 if (mAlias != alias) {  
  23.                     mAlias = alias;  
  24.                     bumpGeneration();  
  25.                 }  
  26.             }  
  27.         }  
  28.   
  29.         size_t numMappers = mMappers.size();  
  30.         for (size_t i = 0; i < numMappers; i++) {  
  31.             InputMapper* mapper = mMappers[i];  
  32.             mapper->configure(when, config, changes);  
  33.             mSources |= mapper->getSources();  
  34.         }  
  35.     }  
  36. }  
因为传入的第三个参数为0,所以这里首先调用EventHub的getConfiguration去获取Input device的idc配置信息。如果设备不是虚拟设备,还需要设置它的layouOverlay和别名,这部分暂时还是实现。我们来看configure的最后一部分,调用mapper转换器的configure方法,为每个mapper转换器做初始化操作,这里主要根据idc文件和input设备的属性来设置mapper的属性。然后调用reset对mapper做重置操作表示设备第一次添加进来,接下来就要正式开始工作了。最后把InputDevice添加到mDevices数组中。
当前面的两个DEVICE_ADDED的event处理完后,接下来就会处理FINISHED_DEVICE_SCAN这个event,我们来看它的处理流程:
[cpp]  view plain  copy
  1. void InputReader::handleConfigurationChangedLocked(nsecs_t when) {  
  2.     // Reset global meta state because it depends on the list of all configured devices.  
  3.     updateGlobalMetaStateLocked();  
  4.   
  5.     // Enqueue configuration changed.  
  6.     NotifyConfigurationChangedArgs args(when);  
  7.     mQueuedListener->notifyConfigurationChanged(&args);  
  8. }  
我们知道mQueuedListener是通过InputDispatcher构造的,这里主要调用mQueuedListener的notifyConfigurationChanged方法会把NotifyConfigurationChangedArgs保存起来,后面通过QueuedInputListener的flush方法会分发给InputDispatcher。
回到InputReader的loopOnce()方法中,当调用processEventsLocked处理完所有的event后,因为当前input设备信息有变化,所以需要调用mPolicy->notifyInputDevicesChanged去通知NativeInputManager有input设备信息变化,在NativeInputManager的notifyInputDevicesChanged函数中,会根据获取到的InputDeviceInfo构造Java层的InputDevice数组,然后调用IMS的notifyInputDevicesChanged方法来告知Java层这时有新的设备添加进来了。最后调用QueuedInputListener的flush方法通知InputDispatcher有config信息变化:
[cpp]  view plain  copy
  1. void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {  
  2.     bool needWake;  
  3.     { // acquire lock  
  4.         AutoMutex _l(mLock);  
  5.   
  6.         ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);  
  7.         needWake = enqueueInboundEventLocked(newEntry);  
  8.     } // release lock  
  9.   
  10.     if (needWake) {  
  11.         mLooper->wake();  
  12.     }  
  13. }  

enqueueInboundEventLocked将newEntry添加到mInboundQueue中,然后调用Looper的wake方法让pollOnce返回,此时再进入到InputDispatcher的dispatchOnce方法中,这里会调用dispatchOnceInnerLocked去分发事件:
[cpp]  view plain  copy
  1. void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {  
  2.     nsecs_t currentTime = now();  
  3.   
  4.     if (!mPolicy->isKeyRepeatEnabled()) {  
  5.         resetKeyRepeatLocked();  
  6.     }  
  7.   
  8.     if (mDispatchFrozen) {  
  9.   
  10.     }  
  11.   
  12.     bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;  
  13.     if (mAppSwitchDueTime < *nextWakeupTime) {  
  14.         *nextWakeupTime = mAppSwitchDueTime;  
  15.     }  
  16.   
  17.     if (! mPendingEvent) {  
  18.         if (mInboundQueue.isEmpty()) {  
  19.   
  20.         } else {  
  21.             mPendingEvent = mInboundQueue.dequeueAtHead();  
  22.             traceInboundQueueLengthLocked();  
  23.         }  
  24.   
  25.         if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {  
  26.         }  
  27.   
  28.         resetANRTimeoutsLocked();  
  29.     }  
  30.   
  31.     bool done = false;  
  32.     DropReason dropReason = DROP_REASON_NOT_DROPPED;  
  33.     if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {  
  34.         dropReason = DROP_REASON_POLICY;  
  35.     } else if (!mDispatchEnabled) {  
  36.         dropReason = DROP_REASON_DISABLED;  
  37.     }  
  38.   
  39.     if (mNextUnblockedEvent == mPendingEvent) {  
  40.         mNextUnblockedEvent = NULL;  
  41.     }  
  42.   
  43.     switch (mPendingEvent->type) {  
  44.     case EventEntry::TYPE_CONFIGURATION_CHANGED: {  
  45.         ConfigurationChangedEntry* typedEntry =  
  46.                 static_cast<ConfigurationChangedEntry*>(mPendingEvent);  
  47.         done = dispatchConfigurationChangedLocked(currentTime, typedEntry);  
  48.         dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped  
  49.         break;  
  50.     }  
  51.   
  52.     }  
  53.   
  54.     if (done) {  
  55.         if (dropReason != DROP_REASON_NOT_DROPPED) {  
  56.             dropInboundEventLocked(mPendingEvent, dropReason);  
  57.         }  
  58.   
  59.         releasePendingEventLocked();  
  60.         *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately  
  61.     }  
  62. }  
在dispatchOnceInnerLocked函数中,首先从mInboundQueue获取刚加入的ConfigurationChangedEntry数据,然后调用dispatchConfigurationChangedLocked去处理这个消息:
[cpp]  view plain  copy
  1. bool InputDispatcher::dispatchConfigurationChangedLocked(  
  2.         nsecs_t currentTime, ConfigurationChangedEntry* entry) {  
  3.     resetKeyRepeatLocked();  
  4.   
  5.     CommandEntry* commandEntry = postCommandLocked(  
  6.             & InputDispatcher::doNotifyConfigurationChangedInterruptible);  
  7.     commandEntry->eventTime = entry->eventTime;  
  8.     return true;  
  9. }  
postCommandLocked将构造一个CommandEntry,它的command是InputDispatcher::doNotifyConfigurationChangedInterruptible函数指针,然后将它加入到mCommandQueue中。并在dispatchOnceInnerLocked中设置下次epoll_wait的timeOut为LONG_LONG_MIN,让epoll_wait马上返回。我们来看下一次调用dispatchOnce时如何处理mCommandQueue的command:
[cpp]  view plain  copy
  1. bool InputDispatcher::runCommandsLockedInterruptible() {  
  2.     if (mCommandQueue.isEmpty()) {  
  3.         return false;  
  4.     }  
  5.   
  6.     do {  
  7.         CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();  
  8.   
  9.         Command command = commandEntry->command;  
  10.         (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'  
  11.   
  12.         commandEntry->connection.clear();  
  13.         delete commandEntry;  
  14.     } while (! mCommandQueue.isEmpty());  
  15.     return true;  
  16. }  
这里主要调用InputDispatcher::doNotifyConfigurationChangedInterruptible方法来执行这个command。
[cpp]  view plain  copy
  1. void InputDispatcher::doNotifyConfigurationChangedInterruptible(  
  2.         CommandEntry* commandEntry) {  
  3.     mLock.unlock();  
  4.   
  5.     mPolicy->notifyConfigurationChanged(commandEntry->eventTime);  
  6.   
  7.     mLock.lock();  
  8. }  

doNotifyConfigurationChangedInterruptible用于向NativeInputManager通知config变化,并最后会通知到Java层的InputMonitor。关于IMS的启动就介绍到这里,来简单总结下IMS的start流程:



触屏事件的分发

从前面介绍EventHub的getEvents方法我们可以知道,当收到触摸屏的点击事件后,则会构造一个RawEvent结构并传递给InputReader的processEventsLocked方法处理,首先来看我们从driver读到到的RawEvent结构:
[cpp]  view plain  copy
  1. struct RawEvent {  
  2.     nsecs_t when;  //发生的时间  
  3.     int32_t deviceId;  //事件发生的deviceId  
  4.     int32_t type;     //事件类型:按键、touch等等  
  5.     int32_t code;    //input事件code码  
  6.     int32_t value;   //input事件值  
  7. };  

当我们点击一次触摸屏时,会发送如下的RawEvent数组过来:
Input event: device=2 type=0x0003 code=0x0030 value=0x00000028 when=119077117000
Input event: device=2 type=0x0003 code=0x0039 value=0x00000000 when=119077136000
Input event: device=2 type=0x0001 code=0x014a value=0x00000001 when=119077153000
Input event: device=2 type=0x0003 code=0x0035 value=0x0000015f when=119077175000
Input event: device=2 type=0x0003 code=0x0036 value=0x00000323 when=119077192000
Input event: device=2 type=0x0000 code=0x0002 value=0x00000000 when=119077208000
Input event: device=2 type=0x0000 code=0x0000 value=0x00000000 when=119077221000

再来分析processEventsLocked处理的代码:
[cpp]  view plain  copy
  1. void InputReader::processEventsForDeviceLocked(int32_t deviceId,  
  2.         const RawEvent* rawEvents, size_t count) {  
  3.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  
  4.     if (deviceIndex < 0) {  
  5.         ALOGW("Discarding event for unknown deviceId %d.", deviceId);  
  6.         return;  
  7.     }  
  8.   
  9.     InputDevice* device = mDevices.valueAt(deviceIndex);  
  10.     if (device->isIgnored()) {  
  11.         //ALOGD("Discarding event for ignored deviceId %d.", deviceId);  
  12.         return;  
  13.     }  
  14.   
  15.     device->process(rawEvents, count);  
  16. }  

这里主要调用首先通过deviceId找到对象的InputDevice,然后调用InputDevice的process方法:
[cpp]  view plain  copy
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) {  
  2.     size_t numMappers = mMappers.size();  
  3.     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {  
  4.         if (mDropUntilNextSync) {  
  5.   
  6.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {  
  7.   
  8.         } else {  
  9.             for (size_t i = 0; i < numMappers; i++) {  
  10.                 InputMapper* mapper = mMappers[i];  
  11.                 mapper->process(rawEvent);  
  12.             }  
  13.         }  
  14.     }  
  15. }  
InputDevice的process方法调用它的依次调用mapper的process方法,因为一个InputDevice既可以移动,也可以点击,所以它可能会有多个mapper,每个mapper分别处理自己关系的事件。这里假设是一个支持多点触摸的touch screen,它的mapper即是MultiTouchInputMapper,调用它的process方法来处理触摸事件:
[cpp]  view plain  copy
  1. void MultiTouchInputMapper::process(const RawEvent* rawEvent) {  
  2.     TouchInputMapper::process(rawEvent);  
  3.   
  4.     mMultiTouchMotionAccumulator.process(rawEvent);  
  5. }  
  6.   
  7. void TouchInputMapper::process(const RawEvent* rawEvent) {  
  8.     mCursorButtonAccumulator.process(rawEvent);  
  9.     mCursorScrollAccumulator.process(rawEvent);  
  10.     mTouchButtonAccumulator.process(rawEvent);  
  11.   
  12.     if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  13.         sync(rawEvent->when);  
  14.     }  
  15. }  

MultiTouchInputMapper是继承于TouchInputMapper,首先调用TouchInputMapper的process方法。在CursorButtonAccumulator的process方法中主要处理鼠标点击事件(左右键等);CursorScrollAccumulator主要用于处理鼠标滚动事件;TouchButtonAccumulator主要用于处理触控笔以及点击事件。所以上面7个RawEvent中,只有type=0x0001,code=0x014a的事件会被TouchButtonAccumulator的process处理。我们依次来看上面7个事件的处理流程:

Input event: device=2 type=0x0003 code=0x0030 value=0x00000028 when=119077117000处理代码在MultiTouchMotionAccumulator::process中:
[cpp]  view plain  copy
  1. case ABS_MT_TOUCH_MAJOR:  
  2.     slot->mInUse = true;  
  3.     slot->mAbsMTTouchMajor = rawEvent->value;  
  4.     break;  

Input event: device=2 type=0x0003 code=0x0039 value=0x00000000 when=119077136000处理代码在MultiTouchMotionAccumulator::process中:
[cpp]  view plain  copy
  1.             case ABS_MT_TRACKING_ID:  
  2.                 if (mUsingSlotsProtocol && rawEvent->value < 0) {  
  3. ;  
  4.                 } else {  
  5.                     slot->mInUse = true;  
  6.                     slot->mAbsMTTrackingId = rawEvent->value;  
  7.                 }  

Input event: device=2 type=0x0001 code=0x014a value=0x00000001 when=119077153000处理代码在TouchButtonAccumulator::process中:
[cpp]  view plain  copy
  1. case BTN_TOUCH:  
  2.     mBtnTouch = rawEvent->value;  
  3.     break;  

Input event: device=2 type=0x0003 code=0x0035 value=0x0000015f when=119077175000处理代码在MultiTouchMotionAccumulator::process中:
[cpp]  view plain  copy
  1. case ABS_MT_POSITION_X:  
  2.     slot->mInUse = true;  
  3.     slot->mAbsMTPositionX = rawEvent->value;  
  4.     break;  

Input event: device=2 type=0x0003 code=0x0036 value=0x00000323 when=119077192000处理代码在MultiTouchMotionAccumulator::process中:
[cpp]  view plain  copy
  1. case ABS_MT_POSITION_Y:  
  2.     slot->mInUse = true;  
  3.     slot->mAbsMTPositionY = rawEvent->value;  
  4.     break;  

Input event: device=2 type=0x0000 code=0x0002 value=0x00000000 when=119077208000处理代码在MultiTouchMotionAccumulator::process中,这里表示一次触摸事件完成:
[cpp]  view plain  copy
  1. else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {  
  2.     mCurrentSlot += 1;  
  3. }  

Input event: device=2 type=0x0000 code=0x0000 value=0x00000000 when=119077221000处理代码在TouchInputMapper::process中,当收到type=EV_SYN,code= SYN_REPORT后,需要去对这次按键做处理:
[cpp]  view plain  copy
  1. if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  2.     sync(rawEvent->when);  
  3. }  

这里调用sync函数去处理这次的按键事件,这个函数比较长,我们分段来分析:
[cpp]  view plain  copy
  1. void TouchInputMapper::sync(nsecs_t when) {.  
  2.     mCurrentButtonState = mTouchButtonAccumulator.getButtonState()  
  3.             | mCursorButtonAccumulator.getButtonState();  
  4.   
  5.     // Sync scroll state.  
  6.     mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();  
  7.     mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();  
  8.     mCursorScrollAccumulator.finishSync();  
  9.   
  10.     // Sync touch state.  
  11.     bool havePointerIds = true;  
  12.     mCurrentRawPointerData.clear();  
  13.     syncTouch(when, &havePointerIds);  

这里首先获取button和鼠标滚动的信息,然后调用syncTouch做准备一个Pointer事件:

[cpp]  view plain  copy
  1. void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {  
  2.     size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();  
  3.     size_t outCount = 0;  
  4.     BitSet32 newPointerIdBits;  
  5.   
  6.     for (size_t inIndex = 0; inIndex < inCount; inIndex++) {  
  7.         const MultiTouchMotionAccumulator::Slot* inSlot =  
  8.                 mMultiTouchMotionAccumulator.getSlot(inIndex);  
  9.         if (!inSlot->isInUse()) {  
  10.             continue;  
  11.         }  
  12.   
  13.         RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];  
  14.         outPointer.x = inSlot->getX();  
  15.         outPointer.y = inSlot->getY();  
  16.         outPointer.pressure = inSlot->getPressure();  
  17.         outPointer.touchMajor = inSlot->getTouchMajor();  
  18.         outPointer.touchMinor = inSlot->getTouchMinor();  
  19.         outPointer.toolMajor = inSlot->getToolMajor();  
  20.         outPointer.toolMinor = inSlot->getToolMinor();  
  21.         outPointer.orientation = inSlot->getOrientation();  
  22.         outPointer.distance = inSlot->getDistance();  
  23.         outPointer.tiltX = 0;  
  24.         outPointer.tiltY = 0;  
  25.   
  26.         outPointer.toolType = inSlot->getToolType();  
  27.         if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {  
  28.             outPointer.toolType = mTouchButtonAccumulator.getToolType();  
  29.             if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {  
  30.                 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;  
  31.             }  
  32.         }  
  33.   
  34.         bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE  
  35.                 && (mTouchButtonAccumulator.isHovering()  
  36.                         || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));  
  37.         outPointer.isHovering = isHovering;  
  38.   
  39.         if (*outHavePointerIds) {  
  40.             int32_t trackingId = inSlot->getTrackingId();  
  41.             int32_t id = -1;  
  42.             if (trackingId >= 0) {  
  43.                 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {  
  44.                     uint32_t n = idBits.clearFirstMarkedBit();  
  45.                     if (mPointerTrackingIdMap[n] == trackingId) {  
  46.                         id = n;  
  47.                     }  
  48.                 }  
  49.   
  50.                 if (id < 0 && !mPointerIdBits.isFull()) {  
  51.                     id = mPointerIdBits.markFirstUnmarkedBit();  
  52.                     mPointerTrackingIdMap[id] = trackingId;  
  53.                 }  
  54.             }  
  55.             if (id < 0) {  
  56.                 *outHavePointerIds = false;  
  57.                 mCurrentRawPointerData.clearIdBits();  
  58.                 newPointerIdBits.clear();  
  59.             } else {  
  60.                 outPointer.id = id;  
  61.                 mCurrentRawPointerData.idToIndex[id] = outCount;  
  62.                 mCurrentRawPointerData.markIdBit(id, isHovering);  
  63.                 newPointerIdBits.markBit(id);  
  64.             }  
  65.         }  
  66.   
  67.         outCount += 1;  
  68.     }  
  69.   
  70.     mCurrentRawPointerData.pointerCount = outCount;  
  71.     mPointerIdBits = newPointerIdBits;  
  72.   
  73.     mMultiTouchMotionAccumulator.finishSync();  
  74. }  

mCurrentRawPointerData这个数据结构中保存此次input事件的个数,并通过其成员pointers数组保存所有的input的信息。并将driver发送过来的trackingId保存在mPointerTrackingIdMap对应的id上,以便后面跟踪使用。对于上面我们介绍的7个event,它们共同促成一个input事件,所以这里的outCount为1。接着来看sync函数:
[cpp]  view plain  copy
  1. mCurrentFingerIdBits.clear();  
  2. mCurrentStylusIdBits.clear();  
  3. mCurrentMouseIdBits.clear();  
  4. mCurrentCookedPointerData.clear();  
  5.   
  6. if (mDeviceMode == DEVICE_MODE_DISABLED) {  
  7.   
  8. else {  
  9.     if (!havePointerIds) {  
  10.     }  
  11.   
  12.     uint32_t policyFlags = 0;  
  13.     bool initialDown = mLastRawPointerData.pointerCount == 0  
  14.             && mCurrentRawPointerData.pointerCount != 0;  
  15.     bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;  
  16.     if (initialDown || buttonsPressed) {  
  17.         if (mDeviceMode == DEVICE_MODE_DIRECT) {  
  18.             getContext()->fadePointer();  
  19.         }  
  20.     }  
  21.       
  22.     //处理button事件,此次触摸事件中并没有touch  
  23.     synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,  
  24.             policyFlags, mLastButtonState, mCurrentButtonState);  
  25.   
  26.     if (consumeRawTouches(when, policyFlags)) {  
  27.         mCurrentRawPointerData.clear();  
  28.     }  

上面的代码中,如果有button事件(如AMOTION_EVENT_BUTTON_BACK、AMOTION_EVENT_BUTTON_FORWARD)发生,则调用synthesizeButtonKeys向InputDispatcher汇报button事件。然后调用consumeRawTouches去检查是否是虚拟事件,因为在Android 4.4中已经不存在虚拟按键,所以我们暂时先不看这个函数。接着往下来看:
[cpp]  view plain  copy
  1.    cookPointerData();  
  2.   
  3.     if (mDeviceMode == DEVICE_MODE_POINTER) {  
  4.   
  5.     } else {  
  6.         if (mDeviceMode == DEVICE_MODE_DIRECT  
  7.                 && mConfig.showTouches && mPointerController != NULL) {  
  8.             mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);  
  9.             mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);  
  10.   
  11.             mPointerController->setButtonState(mCurrentButtonState);  
  12.             mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,  
  13.                     mCurrentCookedPointerData.idToIndex,  
  14.                     mCurrentCookedPointerData.touchingIdBits);  
  15.         }  
  16.   
  17.         dispatchHoverExit(when, policyFlags);  
  18.         dispatchTouches(when, policyFlags);  
  19.         dispatchHoverEnterAndMove(when, policyFlags);  
  20.     }  
  21.   
  22.     // 处理button事件,此次触摸事件中并没有touch  
  23.     synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,  
  24.             policyFlags, mLastButtonState, mCurrentButtonState);  
  25. }  
  26.   
  27. mLastRawPointerData.copyFrom(mCurrentRawPointerData);  
  28. mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);  
  29. mLastButtonState = mCurrentButtonState;  
  30. mLastFingerIdBits = mCurrentFingerIdBits;  
  31. mLastStylusIdBits = mCurrentStylusIdBits;  
  32. mLastMouseIdBits = mCurrentMouseIdBits;  
  33.   
  34. // Clear some transient state.  
  35. mCurrentRawVScroll = 0;  
  36. mCurrentRawHScroll = 0;  

cookPointerData函数用于保存此次input事件,因为当前屏幕是touch screen,所以直接调用dispatchHoverExit、dispatchTouches和dispatchHoverEnterAndMove三个方法来分发事件,如果在Settings中打开了showTouch选项,则调用PointerController去绘制相应的坐标位置。我们首先来看dispatchHoverExit方法:
[cpp]  view plain  copy
  1. void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {  
  2.     if (mSentHoverEnter &&  
  3.             (mCurrentCookedPointerData.hoveringIdBits.isEmpty()  
  4.                     || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {  
  5.   
  6.         mSentHoverEnter = false;  
  7.     }  
  8. }  
因为此时mSentHoverEnter为false,所以这个函数什么也不做,直接返回。接着来看dispatchTouches函数:

[cpp]  view plain  copy
  1. void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {  
  2.     BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;  
  3.     BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;  
  4.     int32_t metaState = getContext()->getGlobalMetaState();  
  5.     int32_t buttonState = mCurrentButtonState;  
  6.   
  7.     if (currentIdBits == lastIdBits) {  
  8.         if (!currentIdBits.isEmpty()) {  
  9.             // No pointer id changes so this is a move event.  
  10.             // The listener takes care of batching moves so we don't have to deal with that here.  
  11.             dispatchMotion(when, policyFlags, mSource,  
  12.                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,  
  13.                     AMOTION_EVENT_EDGE_FLAG_NONE,  
  14.                     mCurrentCookedPointerData.pointerProperties,  
  15.                     mCurrentCookedPointerData.pointerCoords,  
  16.                     mCurrentCookedPointerData.idToIndex,  
  17.                     currentIdBits, -1,  
  18.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  19.         }  
  20.     } else {  
  21.         // There may be pointers going up and pointers going down and pointers moving  
  22.         // all at the same time.  
  23.         BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);  
  24.         BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);  
  25.         BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);  
  26.         BitSet32 dispatchedIdBits(lastIdBits.value);  
  27.   
  28.         // Update last coordinates of pointers that have moved so that we observe the new  
  29.         // pointer positions at the same time as other pointers that have just gone up.  
  30.         bool moveNeeded = updateMovedPointers(  
  31.                 mCurrentCookedPointerData.pointerProperties,  
  32.                 mCurrentCookedPointerData.pointerCoords,  
  33.                 mCurrentCookedPointerData.idToIndex,  
  34.                 mLastCookedPointerData.pointerProperties,  
  35.                 mLastCookedPointerData.pointerCoords,  
  36.                 mLastCookedPointerData.idToIndex,  
  37.                 moveIdBits);  
  38.         if (buttonState != mLastButtonState) {  
  39.             moveNeeded = true;  
  40.         }  
  41.   
  42.         // Dispatch pointer up events.  
  43.         while (!upIdBits.isEmpty()) {  
  44.             uint32_t upId = upIdBits.clearFirstMarkedBit();  
  45.   
  46.             dispatchMotion(when, policyFlags, mSource,  
  47.                     AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,  
  48.                     mLastCookedPointerData.pointerProperties,  
  49.                     mLastCookedPointerData.pointerCoords,  
  50.                     mLastCookedPointerData.idToIndex,  
  51.                     dispatchedIdBits, upId,  
  52.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  53.             dispatchedIdBits.clearBit(upId);  
  54.         }  
  55.   
  56.         // Dispatch move events if any of the remaining pointers moved from their old locations.  
  57.         // Although applications receive new locations as part of individual pointer up  
  58.         // events, they do not generally handle them except when presented in a move event.  
  59.         if (moveNeeded) {  
  60.             ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);  
  61.             dispatchMotion(when, policyFlags, mSource,  
  62.                     AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,  
  63.                     mCurrentCookedPointerData.pointerProperties,  
  64.                     mCurrentCookedPointerData.pointerCoords,  
  65.                     mCurrentCookedPointerData.idToIndex,  
  66.                     dispatchedIdBits, -1,  
  67.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  68.         }  
  69.   
  70.         // Dispatch pointer down events using the new pointer locations.  
  71.         while (!downIdBits.isEmpty()) {  
  72.             uint32_t downId = downIdBits.clearFirstMarkedBit();  
  73.             dispatchedIdBits.markBit(downId);  
  74.   
  75.             if (dispatchedIdBits.count() == 1) {  
  76.                 // First pointer is going down.  Set down time.  
  77.                 mDownTime = when;  
  78.             }  
  79.   
  80.             dispatchMotion(when, policyFlags, mSource,  
  81.                     AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,  
  82.                     mCurrentCookedPointerData.pointerProperties,  
  83.                     mCurrentCookedPointerData.pointerCoords,  
  84.                     mCurrentCookedPointerData.idToIndex,  
  85.                     dispatchedIdBits, downId,  
  86.                     mOrientedXPrecision, mOrientedYPrecision, mDownTime);  
  87.         }  
  88.     }  
  89. }  

dispatchTouches从CurrentCookedPointerData和LastCookedPointerData分别取出touchingIdBits,对两者进行一系列操作获取到当前事件是up、down还是move事件,并分别调用不同的dispatchMotion去分发AMOTION_EVENT_ACTION_POINTER_UP、AMOTION_EVENT_ACTION_POINTER_DOWN和AMOTION_EVENT_ACTION_MOVE事件。我们此次只看AMOTION_EVENT_ACTION_POINTER_DOWN事件的分发:
[cpp]  view plain  copy
  1. void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,  
  2.         int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,  
  3.         const PointerProperties* properties, const PointerCoords* coords,  
  4.         const uint32_t* idToIndex, BitSet32 idBits,  
  5.         int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {  
  6.     PointerCoords pointerCoords[MAX_POINTERS];  
  7.     PointerProperties pointerProperties[MAX_POINTERS];  
  8.     uint32_t pointerCount = 0;  
  9.     while (!idBits.isEmpty()) {  
  10.         uint32_t id = idBits.clearFirstMarkedBit();  
  11.         uint32_t index = idToIndex[id];  
  12.         pointerProperties[pointerCount].copyFrom(properties[index]);  
  13.         pointerCoords[pointerCount].copyFrom(coords[index]);  
  14.   
  15.         if (changedId >= 0 && id == uint32_t(changedId)) {  
  16.             action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;  
  17.         }  
  18.   
  19.         pointerCount += 1;  
  20.     }  
  21.   
  22.     ALOG_ASSERT(pointerCount != 0);  
  23.   
  24.     if (changedId >= 0 && pointerCount == 1) {  
  25.         if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {  
  26.             action = AMOTION_EVENT_ACTION_DOWN;  
  27.         } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {  
  28.             action = AMOTION_EVENT_ACTION_UP;  
  29.         } else {  
  30.             // Can't happen.  
  31.             ALOG_ASSERT(false);  
  32.         }  
  33.     }  
  34.   
  35.     NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,  
  36.             action, flags, metaState, buttonState, edgeFlags,  
  37.             mViewport.displayId, pointerCount, pointerProperties, pointerCoords,  
  38.             xPrecision, yPrecision, downTime);  
  39.     getListener()->notifyMotion(&args);  
  40. }  

这里会对AMOTION_EVENT_ACTION_POINTER_DOWN转换成AMOTION_EVENT_ACTION_DOWN,然后notify给InputDispatcher:
[cpp]  view plain  copy
  1. void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {  
  2.     if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) {  
  3.         return;  
  4.     }  
  5.   
  6.     uint32_t policyFlags = args->policyFlags;  
  7.     policyFlags |= POLICY_FLAG_TRUSTED;  
  8.     mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);  
  9.   
  10.     bool needWake;  
  11.     { // acquire lock  
  12.         mLock.lock();  
  13.   
  14.         if (shouldSendMotionToInputFilterLocked(args)) {  
  15.             mLock.unlock();  
  16.   
  17.             MotionEvent event;  
  18.             event.initialize(args->deviceId, args->source, args->action, args->flags,  
  19.                     args->edgeFlags, args->metaState, args->buttonState, 0, 0,  
  20.                     args->xPrecision, args->yPrecision,  
  21.                     args->downTime, args->eventTime,  
  22.                     args->pointerCount, args->pointerProperties, args->pointerCoords);  
  23.   
  24.             policyFlags |= POLICY_FLAG_FILTERED;  
  25.             if (!mPolicy->filterInputEvent(&event, policyFlags)) {  
  26.                 return// event was consumed by the filter  
  27.             }  
  28.   
  29.             mLock.lock();  
  30.         }  
  31.   
  32.         // Just enqueue a new motion event.  
  33.         MotionEntry* newEntry = new MotionEntry(args->eventTime,  
  34.                 args->deviceId, args->source, policyFlags,  
  35.                 args->action, args->flags, args->metaState, args->buttonState,  
  36.                 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,  
  37.                 args->displayId,  
  38.                 args->pointerCount, args->pointerProperties, args->pointerCoords);  
  39.   
  40.         needWake = enqueueInboundEventLocked(newEntry);  
  41.         mLock.unlock();  
  42.     } // release lock  
  43.   
  44.     if (needWake) {  
  45.         mLooper->wake();  
  46.     }  
  47. }  

在InputDispatcher的notifyMotion函数中,首先检查NotifyMotionArgs是否合法。然后对policyFlags添加上POLICY_FLAG_TRUSTED,并调用NativeInputManager的interceptMotionBeforeQueueing方法对这个input事件提前做处理:
[cpp]  view plain  copy
  1. void NativeInputManager::interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {  
  2.     if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {  
  3.         if (isScreenOn()) {  
  4.             policyFlags |= POLICY_FLAG_PASS_TO_USER;  
  5.   
  6.             if (!isScreenBright()) {  
  7.                 policyFlags |= POLICY_FLAG_BRIGHT_HERE;  
  8.             }  
  9.         } else {  
  10.   
  11.         }  
  12.     } else {  
  13.   
  14.     }  
  15. }  

因为当前屏幕处于点亮状态,这里会对policyFlags添加上POLICY_FLAG_PASS_TO_USER,表示要把这个事件上传给user。

回到notifyMotion中,如果当前设置了InputFilter,则构造一个MotionEvent对象发送给InputFilter处理。如果没有设置InputFilter,则构造一个MotionEntry,并添加到mInboundQueue中,并唤醒InputDispatcher的dispatchOnce方法,并调用dispatchOnceInnerLocked去完成事件的分发:
[cpp]  view plain  copy
  1. void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {  
  2.     nsecs_t currentTime = now();  
  3.       
  4.     bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;  
  5.     if (mAppSwitchDueTime < *nextWakeupTime) {  
  6.         *nextWakeupTime = mAppSwitchDueTime;  
  7.     }  
  8.       
  9.     if (! mPendingEvent) {  
  10.         if (mInboundQueue.isEmpty()) {  
  11.   
  12.         } else {  
  13.             mPendingEvent = mInboundQueue.dequeueAtHead();  
  14.             traceInboundQueueLengthLocked();  
  15.         }  
  16.           
  17.         if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {  
  18.             pokeUserActivityLocked(mPendingEvent);  
  19.         }  
  20.   
  21.         resetANRTimeoutsLocked();  
  22.     }  
  23.   
  24.     ALOG_ASSERT(mPendingEvent != NULL);  
  25.     bool done = false;  
  26.     DropReason dropReason = DROP_REASON_NOT_DROPPED;  
  27.     if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {  
  28.   
  29.     } else if (!mDispatchEnabled) {  
  30.   
  31.     }  
  32.   
  33.     if (mNextUnblockedEvent == mPendingEvent) {  
  34.         mNextUnblockedEvent = NULL;  
  35.     }  
  36.   
  37.     switch (mPendingEvent->type) {  
  38.   
  39.     case EventEntry::TYPE_MOTION: {  
  40.         MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);  
  41.         if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {  
  42.   
  43.         }  
  44.         if (dropReason == DROP_REASON_NOT_DROPPED  
  45.                 && isStaleEventLocked(currentTime, typedEntry)) {  
  46.   
  47.         }  
  48.         if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {  
  49.   
  50.         }  
  51.         done = dispatchMotionLocked(currentTime, typedEntry,  
  52.                 &dropReason, nextWakeupTime);  
  53.         break;  
  54.     }  
  55.   
  56.     default:  
  57.         ALOG_ASSERT(false);  
  58.         break;  
  59.     }  
  60.   
  61.     if (done) {  
  62.         if (dropReason != DROP_REASON_NOT_DROPPED) {  
  63.             dropInboundEventLocked(mPendingEvent, dropReason);  
  64.         }  
  65.   
  66.         releasePendingEventLocked();  
  67.         *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately  
  68.     }  
  69. }  

这里首先从mInboundQueue中获取前面添加的MotionEntry对象,然后调用dispatchMotionLocked去分发:
[cpp]  view plain  copy
  1. bool InputDispatcher::dispatchMotionLocked(  
  2.         nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {  
  3.     if (! entry->dispatchInProgress) {  
  4.         entry->dispatchInProgress = true;  
  5.     }  
  6.   
  7.     if (*dropReason != DROP_REASON_NOT_DROPPED) {  
  8.   
  9.     }  
  10.   
  11.     bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;  
  12.   
  13.     Vector<InputTarget> inputTargets;  
  14.   
  15.     bool conflictingPointerActions = false;  
  16.     int32_t injectionResult;  
  17.     if (isPointerEvent) {  
  18.         injectionResult = findTouchedWindowTargetsLocked(currentTime,  
  19.                 entry, inputTargets, nextWakeupTime, &conflictingPointerActions);  
  20.     } else {  
  21.   
  22.     }  
  23.     if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {  
  24.   
  25.     }  
  26.   
  27.     setInjectionResultLocked(entry, injectionResult);  
  28.     if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {  
  29.         return true;  
  30.     }  
  31.   
  32.     if (isMainDisplay(entry->displayId)) {  
  33.         addMonitoringTargetsLocked(inputTargets);  
  34.     }  
  35.   
  36.     // Dispatch the motion.  
  37.     if (conflictingPointerActions) {  
  38.         CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,  
  39.                 "conflicting pointer actions");  
  40.         synthesizeCancelationEventsForAllConnectionsLocked(options);  
  41.     }  
  42.     dispatchEventLocked(currentTime, entry, inputTargets);  
  43.     return true;  
  44. }  

在dispatchMotionLocked中,首先调用findTouchedWindowTargetsLocked去找到有focus的window窗口,并把这些创建保存在inputTargets数组中。并且还记得我们前面有注册一个monitor的InputChannel吗?这里也会调用addMonitoringTargetsLocked把mMonitoringChannels中所有的InputChannel添加到inputTargets数组中。然后调用dispatchEventLocked去向这些窗口一个个分发事件。我们先来看findTouchedWindowTargetsLocked方法:
[cpp]  view plain  copy
  1. int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,  
  2.         const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,  
  3.         bool* outConflictingPointerActions) {  
  4.     enum InjectionPermission {  
  5.         INJECTION_PERMISSION_UNKNOWN,  
  6.         INJECTION_PERMISSION_GRANTED,  
  7.         INJECTION_PERMISSION_DENIED  
  8.     };  
  9.   
  10.     nsecs_t startTime = now();  
  11.     bool screenWasOff = false;  
  12.   
  13.     int32_t displayId = entry->displayId;  
  14.     int32_t action = entry->action;  
  15.     int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;  
  16.   
  17.     // Update the touch state as needed based on the properties of the touch event.  
  18.     int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;  
  19.     InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;  
  20.     sp<InputWindowHandle> newHoverWindowHandle;  
  21.   
  22.     bool isSplit = mTouchState.split;  
  23.     bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0  
  24.             && (mTouchState.deviceId != entry->deviceId  
  25.                     || mTouchState.source != entry->source  
  26.                     || mTouchState.displayId != displayId);  
  27.     bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE  
  28.             || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER  
  29.             || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);  
  30.     bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN  
  31.             || maskedAction == AMOTION_EVENT_ACTION_SCROLL  
  32.             || isHoverAction);  
  33.     bool wrongDevice = false;  
  34.     if (newGesture) {  
  35.         bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;  
  36.         if (switchedDevice && mTouchState.down && !down) {  
  37.   
  38.         }  
  39.         mTempTouchState.reset();  
  40.         mTempTouchState.down = down;  
  41.         mTempTouchState.deviceId = entry->deviceId;  
  42.         mTempTouchState.source = entry->source;  
  43.         mTempTouchState.displayId = displayId;  
  44.         isSplit = false;  
  45.     } else {  
  46.   
  47.     }  
  48.   
  49.     if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {  
  50.         int32_t pointerIndex = getMotionEventActionPointerIndex(action);  
  51.         int32_t x = int32_t(entry->pointerCoords[pointerIndex].  
  52.                 getAxisValue(AMOTION_EVENT_AXIS_X));  
  53.         int32_t y = int32_t(entry->pointerCoords[pointerIndex].  
  54.                 getAxisValue(AMOTION_EVENT_AXIS_Y));  
  55.         sp<InputWindowHandle> newTouchedWindowHandle;  
  56.         sp<InputWindowHandle> topErrorWindowHandle;  
  57.         bool isTouchModal = false;  
  58.   
  59.         size_t numWindows = mWindowHandles.size();  
  60.         for (size_t i = 0; i < numWindows; i++) {  
  61.             sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);  
  62.             const InputWindowInfo* windowInfo = windowHandle->getInfo();  
  63.             if (windowInfo->displayId != displayId) {  
  64.                 continue// wrong display  
  65.             }  
  66.   
  67.             int32_t flags = windowInfo->layoutParamsFlags;  
  68.             if (windowInfo->visible) {  
  69.                 if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {  
  70.                     isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE  
  71.                             | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;  
  72.                     if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {  
  73.                         if (! screenWasOff  
  74.                                 || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) {  
  75.                             newTouchedWindowHandle = windowHandle;  
  76.                         }  
  77.                         break// found touched window, exit window loop  
  78.                     }  
  79.                 }  
  80.             }  
  81.         }  
  82.   
  83.         if (newTouchedWindowHandle != NULL  
  84.                 && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {  
  85.             isSplit = true;  
  86.         } else if (isSplit) {  
  87.         }  
  88.   
  89.         int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;  
  90.         if (isSplit) {  
  91.             targetFlags |= InputTarget::FLAG_SPLIT;  
  92.         }  
  93.         if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {  
  94.             targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;  
  95.         }  
  96.   
  97.         BitSet32 pointerIds;  
  98.         if (isSplit) {  
  99.             uint32_t pointerId = entry->pointerProperties[pointerIndex].id;  
  100.             pointerIds.markBit(pointerId);  
  101.         }  
  102.         mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);  
  103.     } else {  
  104.   
  105.     }  
  106.   
  107.     {  
  108.         bool haveForegroundWindow = false;  
  109.         for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {  
  110.             const TouchedWindow& touchedWindow = mTempTouchState.windows[i];  
  111.             if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {  
  112.                 haveForegroundWindow = true;  
  113.                 if (! checkInjectionPermission(touchedWindow.windowHandle,  
  114.                         entry->injectionState)) {  
  115.                     injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;  
  116.                     injectionPermission = INJECTION_PERMISSION_DENIED;  
  117.                     goto Failed;  
  118.                 }  
  119.             }  
  120.         }  
  121.   
  122.         injectionPermission = INJECTION_PERMISSION_GRANTED;  
  123.     }  
  124.   
  125.     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {  
  126.         sp<InputWindowHandle> foregroundWindowHandle =  
  127.                 mTempTouchState.getFirstForegroundWindowHandle();  
  128.         const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;  
  129.         for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {  
  130.             const TouchedWindow& touchedWindow = mTempTouchState.windows[i];  
  131.             if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {  
  132.                 sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;  
  133.                 if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {  
  134.                     mTempTouchState.addOrUpdateWindow(inputWindowHandle,  
  135.                             InputTarget::FLAG_ZERO_COORDS, BitSet32(0));  
  136.                 }  
  137.             }  
  138.         }  
  139.     }  
  140.   
  141.     if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {  
  142.         sp<InputWindowHandle> foregroundWindowHandle =  
  143.                 mTempTouchState.getFirstForegroundWindowHandle();  
  144.         if (foregroundWindowHandle->getInfo()->hasWallpaper) {  
  145.             for (size_t i = 0; i < mWindowHandles.size(); i++) {  
  146.                 sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);  
  147.                 const InputWindowInfo* info = windowHandle->getInfo();  
  148.                 if (info->displayId == displayId  
  149.                         && windowHandle->getInfo()->layoutParamsType  
  150.                                 == InputWindowInfo::TYPE_WALLPAPER) {  
  151.                     mTempTouchState.addOrUpdateWindow(windowHandle,  
  152.                             InputTarget::FLAG_WINDOW_IS_OBSCURED  
  153.                                     | InputTarget::FLAG_DISPATCH_AS_IS,  
  154.                             BitSet32(0));  
  155.                 }  
  156.             }  
  157.         }  
  158.     }  
  159.   
  160.     injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;  
  161.   
  162.     for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {  
  163.         const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);  
  164.         addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,  
  165.                 touchedWindow.pointerIds, inputTargets);  
  166.     }  
  167.   
  168.     mTempTouchState.filterNonAsIsTouchWindows();  
  169.     return injectionResult;  
  170. }  

findTouchedWindowTargetsLocked方法首先根据我们这次触摸事件去判断是down、up还是move,然后调用不同的处理方法来处理。我们来只看一次down事件,首先从mWindowHandles找到当前focus焦点的window、获取点击区域在window中的窗口或者InputWindowInfo设置了FLAG_WATCH_OUTSIDE_TOUCH的所有窗口,并把这些窗口全部放在mTempTouchState的windows中。然后对这些创建做权限检查以及这个窗口是否处于paused状态,并从mTempTouchState中移除这些窗口。最后把检查过的所有window的inputChannel全部放到inputTargets数组中。
回到dispatchMotionLocked函数中,接着调用dispatchEventLocked函数去一个一个向inputTargets中的inputChannel分发input事件:
[cpp]  view plain  copy
  1. void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,  
  2.         EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {  
  3.     pokeUserActivityLocked(eventEntry);  
  4.   
  5.     for (size_t i = 0; i < inputTargets.size(); i++) {  
  6.         const InputTarget& inputTarget = inputTargets.itemAt(i);  
  7.   
  8.         ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);  
  9.         if (connectionIndex >= 0) {  
  10.             sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);  
  11.             prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);  
  12.         } else {  
  13.   
  14.         }  
  15.     }  
  16. }  

我们前面介绍InputManagerService的monitorInput方法时讲解过,在向InputDispatcher注册InputChannel时,会构造一个Connection对象并保存InputChannel,这个Connection对象是通过Fd值保存在mConnectionsByFd数组中。这里getConnectionIndexLocked首先获取window所注册的InputChannel,然后调用prepareDispatchCycleLocked去准备分发:
[cpp]  view plain  copy
  1. void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,  
  2.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {  
  3.     enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);  
  4. }  
  5.   
  6. void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,  
  7.         const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {  
  8.     bool wasEmpty = connection->outboundQueue.isEmpty();  
  9.   
  10.     // Enqueue dispatch entries for the requested modes.  
  11.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  12.             InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);  
  13.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  14.             InputTarget::FLAG_DISPATCH_AS_OUTSIDE);  
  15.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  16.             InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);  
  17.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  18.             InputTarget::FLAG_DISPATCH_AS_IS);  
  19.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  20.             InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);  
  21.     enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,  
  22.             InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);  
  23.   
  24.     // If the outbound queue was previously empty, start the dispatch cycle going.  
  25.     if (wasEmpty && !connection->outboundQueue.isEmpty()) {  
  26.         startDispatchCycleLocked(currentTime, connection);  
  27.     }  
  28. }  

prepareDispatchCycleLocked主要调用enqueueDispatchEntriesLocked把当前EventEntry添加到connection的outboundQueue中。enqueueDispatchEntryLocked函数会根据inputTarget的flags和dispatchMode比较,如果两者没有交集,就不将EventEntry添加到outboundQueue。最后调用startDispatchCycleLocked去分发这个这个事件:
[cpp]  view plain  copy
  1. void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,  
  2.         const sp<Connection>& connection) {  
  3.     while (connection->status == Connection::STATUS_NORMAL  
  4.             && !connection->outboundQueue.isEmpty()) {  
  5.         DispatchEntry* dispatchEntry = connection->outboundQueue.head;  
  6.         dispatchEntry->deliveryTime = currentTime;  
  7.   
  8.         status_t status;  
  9.         EventEntry* eventEntry = dispatchEntry->eventEntry;  
  10.         switch (eventEntry->type) {  
  11.         case EventEntry::TYPE_MOTION: {  
  12.             MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);  
  13.   
  14.             PointerCoords scaledCoords[MAX_POINTERS];  
  15.             const PointerCoords* usingCoords = motionEntry->pointerCoords;  
  16.   
  17.             float xOffset, yOffset, scaleFactor;  
  18.             if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)  
  19.                     && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {  
  20.                 scaleFactor = dispatchEntry->scaleFactor;  
  21.                 xOffset = dispatchEntry->xOffset * scaleFactor;  
  22.                 yOffset = dispatchEntry->yOffset * scaleFactor;  
  23.                 if (scaleFactor != 1.0f) {  
  24.                     for (size_t i = 0; i < motionEntry->pointerCount; i++) {  
  25.                         scaledCoords[i] = motionEntry->pointerCoords[i];  
  26.                         scaledCoords[i].scale(scaleFactor);  
  27.                     }  
  28.                     usingCoords = scaledCoords;  
  29.                 }  
  30.             } else {  
  31.                 xOffset = 0.0f;  
  32.                 yOffset = 0.0f;  
  33.                 scaleFactor = 1.0f;  
  34.   
  35.                 // We don't want the dispatch target to know.  
  36.                 if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {  
  37.                     for (size_t i = 0; i < motionEntry->pointerCount; i++) {  
  38.                         scaledCoords[i].clear();  
  39.                     }  
  40.                     usingCoords = scaledCoords;  
  41.                 }  
  42.             }  
  43.   
  44.             status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,  
  45.                     motionEntry->deviceId, motionEntry->source,  
  46.                     dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,  
  47.                     motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,  
  48.                     xOffset, yOffset,  
  49.                     motionEntry->xPrecision, motionEntry->yPrecision,  
  50.                     motionEntry->downTime, motionEntry->eventTime,  
  51.                     motionEntry->pointerCount, motionEntry->pointerProperties,  
  52.                     usingCoords);  
  53.             break;  
  54.         }  
  55.   
  56.         default:  
  57.             ALOG_ASSERT(false);  
  58.             return;  
  59.         }  
  60.   
  61.         // Re-enqueue the event on the wait queue.  
  62.         connection->outboundQueue.dequeue(dispatchEntry);  
  63.         traceOutboundQueueLengthLocked(connection);  
  64.         connection->waitQueue.enqueueAtTail(dispatchEntry);  
  65.         traceWaitQueueLengthLocked(connection);  
  66.     }  
  67. }  

在startDispatchCycleLocked函数中调用inputPublisher的publishMotionEvent将这次触摸事件发送出去,并把dispatchEntry从outboundQueue中移除并添加到waitQueue中。inputPublisher的publishMotionEvent方法最终会调用到InputChannel的sendMessage方法通过socket发送给client端。到这里InputReader和InputDispatcher就成功了处理了一次input事件,并通过InputChannel发送给了client端。

还记得我们前面注册一个monitor的InputChannel吗?这里发送了一个触摸事件,我们来看client如何接受消息,因为在NativeInputEventReceiver的initialize函数中,我们通过Looper的addFd讲client端的InputChannel绑定到了epoll_wait中,当server端发送数据后,就会调用handleEvent来处理:
[cpp]  view plain  copy
  1. int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {  
  2.     if (events & ALOOPER_EVENT_INPUT) {  
  3.         JNIEnv* env = AndroidRuntime::getJNIEnv();  
  4.         status_t status = consumeEvents(env, false /*consumeBatches*/, -1);  
  5.         mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");  
  6.         return status == OK || status == NO_MEMORY ? 1 : 0;  
  7.     }  
  8. }  
  9.   
  10. status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,  
  11.         bool consumeBatches, nsecs_t frameTime) {  
  12.     ScopedLocalRef<jobject> receiverObj(env, NULL);  
  13.     bool skipCallbacks = false;  
  14.     for (;;) {  
  15.         uint32_t seq;  
  16.         InputEvent* inputEvent;  
  17.         status_t status = mInputConsumer.consume(&mInputEventFactory,  
  18.                 consumeBatches, frameTime, &seq, &inputEvent);  
  19.         if (!skipCallbacks) {  
  20.             if (!receiverObj.get()) {  
  21.                 receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));  
  22.             }  
  23.   
  24.             jobject inputEventObj;  
  25.             switch (inputEvent->getType()) {  
  26.   
  27.             case AINPUT_EVENT_TYPE_MOTION:  
  28.                 inputEventObj = android_view_MotionEvent_obtainAsCopy(env,  
  29.                         static_cast<MotionEvent*>(inputEvent));  
  30.                 break;  
  31.   
  32.             default:  
  33.                 assert(false); // InputConsumer should prevent this from ever happening  
  34.                 inputEventObj = NULL;  
  35.             }  
  36.   
  37.             if (inputEventObj) {  
  38.                 env->CallVoidMethod(receiverObj.get(),  
  39.                         gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);  
  40.                 if (env->ExceptionCheck()) {  
  41.   
  42.                 }  
  43.                 env->DeleteLocalRef(inputEventObj);  
  44.             } else {  
  45.   
  46.             }  
  47.         }  
  48.     }  
  49. }  

在handleEvent调用consumeEvents来消化这个event事件,consumeEvents首先调用InputConsumer的consume方法去获取这次触摸事件到InputEvent中:
[cpp]  view plain  copy
  1. status_t InputConsumer::consume(InputEventFactoryInterface* factory,  
  2.         bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {  
  3.     *outSeq = 0;  
  4.     *outEvent = NULL;  
  5.   
  6.     while (!*outEvent) {  
  7.         if (mMsgDeferred) {  
  8.   
  9.         } else {  
  10.             status_t result = mChannel->receiveMessage(&mMsg);  
  11.         }  
  12.   
  13.         switch (mMsg.header.type) {  
  14.         case AINPUT_EVENT_TYPE_MOTION: {  
  15.             MotionEvent* motionEvent = factory->createMotionEvent();  
  16.             if (! motionEvent) return NO_MEMORY;  
  17.   
  18.             updateTouchState(&mMsg);  
  19.             initializeMotionEvent(motionEvent, &mMsg);  
  20.             *outSeq = mMsg.body.motion.seq;  
  21.             *outEvent = motionEvent;  
  22.             break;  
  23.         }  
  24.     }  
  25.     return OK;  
  26. }  
consume函数调用InputChannel的receiverMessage方法从socket中获取server端传输过来的msg,然后调用initializeMotionEvent去初始化一个MotionEvent并返回给consumeEvents函数。consumeEvents最终调用InputEventReceiver的dispatchInputEvent方法将此次触摸事件传递给Java层。
[cpp]  view plain  copy
  1. public void onInputEvent(InputEvent event) {  
  2.     try {  
  3.         if (event instanceof MotionEvent  
  4.                 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {  
  5.             final MotionEvent motionEvent = (MotionEvent)event;  
  6.             PointerEventListener[] listeners;  
  7.             synchronized (mListeners) {  
  8.                 if (mListenersArray == null) {  
  9.                     mListenersArray = new PointerEventListener[mListeners.size()];  
  10.                     mListeners.toArray(mListenersArray);  
  11.                 }  
  12.                 listeners = mListenersArray;  
  13.             }  
  14.             for (int i = 0; i < listeners.length; ++i) {  
  15.                 listeners[i].onPointerEvent(motionEvent);  
  16.             }  
  17.         }  
  18.     } finally {  
  19.         finishInputEvent(event, false);  
  20.     }  
  21. }  

PointerEventDispatcher继承于InputEventReceiver,在它的onInputEvent中会回调所有listeners的onPointerEvent方法,并调用finishInputEvent去通知InputDispatch这个消息有没有被处理:
[cpp]  view plain  copy
  1.     public final void finishInputEvent(InputEvent event, boolean handled) {  
  2.             int index = mSeqMap.indexOfKey(event.getSequenceNumber());  
  3.             if (index < 0) {  
  4.             } else {  
  5.                 int seq = mSeqMap.valueAt(index);  
  6.                 mSeqMap.removeAt(index);  
  7.                 nativeFinishInputEvent(mReceiverPtr, seq, handled);  
  8.             }  
  9.         event.recycleIfNeededAfterDispatch();  
  10.     }  
  11.   
  12. static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jint receiverPtr,  
  13.         jint seq, jboolean handled) {  
  14.     sp<NativeInputEventReceiver> receiver =  
  15.             reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);  
  16.     status_t status = receiver->finishInputEvent(seq, handled);  
  17.     if (status && status != DEAD_OBJECT) {  
  18.   
  19.     }  
  20. }  

这里通过JNI调用到NativeInputEventReceiver的finishInputEvent方法:
[cpp]  view plain  copy
  1. status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {  
  2.     status_t status = mInputConsumer.sendFinishedSignal(seq, handled);  
  3.     return status;  
  4. }  
  5.   
  6. status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {  
  7.     size_t seqChainCount = mSeqChains.size();  
  8.     if (seqChainCount) {  
  9.   
  10.     }  
  11.     return sendUnchainedFinishedSignal(seq, handled);  
  12. }  
  13.   
  14. status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {  
  15.     InputMessage msg;  
  16.     msg.header.type = InputMessage::TYPE_FINISHED;  
  17.     msg.body.finished.seq = seq;  
  18.     msg.body.finished.handled = handled;  
  19.     return mChannel->sendMessage(&msg);  
  20. }  

这里最终会调用client端的InputChannel向server发送个一个InputMessage,用于通知InputDispatcher当前消息的处理结果,我们回到InputDihandleReceiveCallbackspatcher当中,来看它如何处理收到的处理结果:
[cpp]  view plain  copy
  1. int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {  
  2.     InputDispatcher* d = static_cast<InputDispatcher*>(data);  
  3.     { // acquire lock  
  4.         AutoMutex _l(d->mLock);  
  5.         ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);  
  6.   
  7.         bool notify;  
  8.         sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);  
  9.         if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {  
  10.             nsecs_t currentTime = now();  
  11.             bool gotOne = false;  
  12.             status_t status;  
  13.             for (;;) {  
  14.                 uint32_t seq;  
  15.                 bool handled;  
  16.                 status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);  
  17.                 if (status) {  
  18.                     break;  
  19.                 }  
  20.                 d->finishDispatchCycleLocked(currentTime, connection, seq, handled);  
  21.                 gotOne = true;  
  22.             }  
  23.             if (gotOne) {  
  24.                 d->runCommandsLockedInterruptible();  
  25.                 if (status == WOULD_BLOCK) {  
  26.                     return 1;  
  27.                 }  
  28.             }  

handleReceiveCallback从InputChannel循环的读取消息,直到遇到WOULD_BLOCK的错误才退出。finishDispatchCycleLocked用于处理接收到的InputMessage:
[cpp]  view plain  copy
  1. void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,  
  2.         const sp<Connection>& connection, uint32_t seq, bool handled) {  
  3.     connection->inputPublisherBlocked = false;  
  4.   
  5.     // Notify other system components and prepare to start the next dispatch cycle.  
  6.     onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);  
  7. }  
  8.   
  9. void InputDispatcher::onDispatchCycleFinishedLocked(  
  10.         nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {  
  11.     CommandEntry* commandEntry = postCommandLocked(  
  12.             & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);  
  13.     commandEntry->connection = connection;  
  14.     commandEntry->eventTime = currentTime;  
  15.     commandEntry->seq = seq;  
  16.     commandEntry->handled = handled;  
  17. }  

这里向mCommandQueue中post一个doDispatchCycleFinishedLockedInterruptible消息。回到handleReceiveCallback中,后面会调用runCommandsLockedInterruptible来执行这个消息:

[cpp]  view plain  copy
  1. void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(  
  2.         CommandEntry* commandEntry) {  
  3.     sp<Connection> connection = commandEntry->connection;  
  4.     nsecs_t finishTime = commandEntry->eventTime;  
  5.     uint32_t seq = commandEntry->seq;  
  6.     bool handled = commandEntry->handled;  
  7.   
  8.     DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);  
  9.     if (dispatchEntry) {  
  10.         nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;  
  11.   
  12.         bool restartEvent;  
  13.         if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {  
  14.   
  15.         } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {  
  16.             MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);  
  17.             restartEvent = afterMotionEventLockedInterruptible(connection,  
  18.                     dispatchEntry, motionEntry, handled);  
  19.         } else {  
  20.         }  
  21.   
  22.         if (dispatchEntry == connection->findWaitQueueEntry(seq)) {  
  23.             connection->waitQueue.dequeue(dispatchEntry);  
  24.             traceWaitQueueLengthLocked(connection);  
  25.             if (restartEvent && connection->status == Connection::STATUS_NORMAL) {  
  26.   
  27.             } else {  
  28.                 releaseDispatchEntryLocked(dispatchEntry);  
  29.             }  
  30.         }  
  31.   
  32.         // Start the next dispatch cycle for this connection.  
  33.         startDispatchCycleLocked(now(), connection);  
  34.     }  
  35. }  

doDispatchCycleFinishedLockedInterruptible首先从connection的waitQueue中移除前面发送过程中添加进去的InputEvent,然后调用startDispatchCycleLocked接着发送connection的outboundQueue中的InputEvent。

Keyboard事件的分发

这里以按一次power键为例来介绍keyboard事件的处理以及分发,以下是按下和松开power键时从EventHub获取到的RawEvent:
按下:
Input event: device=1 type=0x0001 code=0x0074 value=0x00000001 when=97560822148000
Input event: device=1 type=0x0000 code=0x0000 value=0x00000000 when=97560822161000

松开:
Input event: device=1 type=0x0001 code=0x0074 value=0x00000000 when=97560974224000
Input event: device=1 type=0x0000 code=0x0000 value=0x00000000 when=97560974234000

还是从processEventsLocked处理的代码开始分析:
[cpp]  view plain  copy
  1. void InputReader::processEventsForDeviceLocked(int32_t deviceId,  
  2.         const RawEvent* rawEvents, size_t count) {  
  3.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  
  4.     if (deviceIndex < 0) {  
  5.         ALOGW("Discarding event for unknown deviceId %d.", deviceId);  
  6.         return;  
  7.     }  
  8.   
  9.     InputDevice* device = mDevices.valueAt(deviceIndex);  
  10.     if (device->isIgnored()) {  
  11.         //ALOGD("Discarding event for ignored deviceId %d.", deviceId);  
  12.         return;  
  13.     }  
  14.   
  15.     device->process(rawEvents, count);  
  16. }  

这里主要调用首先通过deviceId找到对象的InputDevice,然后调用InputDevice的process方法:
[cpp]  view plain  copy
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) {  
  2.     size_t numMappers = mMappers.size();  
  3.     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {  
  4.         if (mDropUntilNextSync) {  
  5.   
  6.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {  
  7.   
  8.         } else {  
  9.             for (size_t i = 0; i < numMappers; i++) {  
  10.                 InputMapper* mapper = mMappers[i];  
  11.                 mapper->process(rawEvent);  
  12.             }  
  13.         }  
  14.     }  
  15. }  

因为当前InputDevice的class是Keyboard,所以这里就会调用KeyboardInputMapper的process来处理:
[cpp]  view plain  copy
  1. void KeyboardInputMapper::process(const RawEvent* rawEvent) {  
  2.     switch (rawEvent->type) {  
  3.     case EV_KEY: {  
  4.         int32_t scanCode = rawEvent->code;  
  5.         int32_t usageCode = mCurrentHidUsage;  
  6.         mCurrentHidUsage = 0;  
  7.   
  8.         if (isKeyboardOrGamepadKey(scanCode)) {  
  9.             int32_t keyCode;  
  10.             uint32_t flags;  
  11.             if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {  
  12.                 keyCode = AKEYCODE_UNKNOWN;  
  13.                 flags = 0;  
  14.             }  
  15.             processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);  
  16.         }  
  17.         break;  
  18.     }  
  19.     case EV_MSC: {  
  20.         if (rawEvent->code == MSC_SCAN) {  
  21.             mCurrentHidUsage = rawEvent->value;  
  22.         }  
  23.         break;  
  24.     }  
  25.     case EV_SYN: {  
  26.         if (rawEvent->code == SYN_REPORT) {  
  27.             mCurrentHidUsage = 0;  
  28.         }  
  29.     }  
  30.     }  
  31. }  

这里首先调用当前Input设备的KeyCharacterMap和Keylayout文件去将RawEvent(Linux Key Code)转换为Android KeyCode。在隐射按键时,会经历两次转换:

1.将Linux Key Code通过.kcm或者.kl文件转换为Android KeyCode标签码
2.通过KeycodeLabel将Android KeyCode标签码转换为Android KeyCode

[cpp]  view plain  copy
  1. status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,  
  2.         int32_t* outKeycode, uint32_t* outFlags) const {  
  3.     AutoMutex _l(mLock);  
  4.     Device* device = getDeviceLocked(deviceId);  
  5.   
  6.     if (device) {  
  7.         // Check the key character map first.  
  8.         sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();  
  9.         if (kcm != NULL) {  
  10.             if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {  
  11.                 *outFlags = 0;  
  12.                 return NO_ERROR;  
  13.             }  
  14.         }  
  15.   
  16.         // Check the key layout next.  
  17.         if (device->keyMap.haveKeyLayout()) {  
  18.             if (!device->keyMap.keyLayoutMap->mapKey(  
  19.                     scanCode, usageCode, outKeycode, outFlags)) {  
  20.                 return NO_ERROR;  
  21.             }  
  22.         }  
  23.     }  
  24.   
  25.     *outKeycode = 0;  
  26.     *outFlags = 0;  
  27.     return NAME_NOT_FOUND;  
  28. }  

从mapKey的实现来看,首先调用KeyCharacterMap去隐射按键,如果没有隐射成功,就再调用Keylayout去隐射按键。从上面的RawEvent的code=0x0074,我们可以从Generic.kl中看到:
[html]  view plain  copy
  1. key 116   POWER             WAKE   

然后在KeycodeLabel中可以看到:
[html]  view plain  copy
  1. { "POWER", 26 },  

所以KeyboardInputMapper的process中的keyCode就是26。接着调用processKey来处理:
[cpp]  view plain  copy
  1. void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,  
  2.         int32_t scanCode, uint32_t policyFlags) {  
  3.   
  4.     if (down) {  
  5.         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {  
  6.             keyCode = rotateKeyCode(keyCode, mOrientation);  
  7.         }  
  8.   
  9.         // Add key down.  
  10.         ssize_t keyDownIndex = findKeyDown(scanCode);  
  11.         if (keyDownIndex >= 0) {  
  12.   
  13.         } else {  
  14.             // key down  
  15.             if ((policyFlags & POLICY_FLAG_VIRTUAL)  
  16.                     && mContext->shouldDropVirtualKey(when,  
  17.                             getDevice(), keyCode, scanCode)) {  
  18.                 return;  
  19.             }  
  20.   
  21.             mKeyDowns.push();  
  22.             KeyDown& keyDown = mKeyDowns.editTop();  
  23.             keyDown.keyCode = keyCode;  
  24.             keyDown.scanCode = scanCode;  
  25.         }  
  26.   
  27.         mDownTime = when;  
  28.     } else {  
  29.   
  30.     }  
  31.   
  32.     bool metaStateChanged = false;  
  33.     int32_t oldMetaState = mMetaState;  
  34.     int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);  
  35.     if (oldMetaState != newMetaState) {  
  36.         mMetaState = newMetaState;  
  37.         metaStateChanged = true;  
  38.         updateLedState(false);  
  39.     }  
  40.   
  41.     nsecs_t downTime = mDownTime;  
  42.     if (down && getDevice()->isExternal()  
  43.             && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {  
  44.         policyFlags |= POLICY_FLAG_WAKE_DROPPED;  
  45.     }  
  46.   
  47.     if (metaStateChanged) {  
  48.         getContext()->updateGlobalMetaState();  
  49.     }  
  50.   
  51.     if (down && !isMetaKey(keyCode)) {  
  52.         getContext()->fadePointer();  
  53.     }  
  54.   
  55.     NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,  
  56.             down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,  
  57.             AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);  
  58.     getListener()->notifyKey(&args);  
  59. }  

processKey根据是按下还是松开分开处理,我们首先来看按下的处理流程:首先构造一个KeyDown对象,并填充它的keyCode和scanCode值。然后向InputDispatch通知AKEY_EVENT_ACTION_DOWN事件:
[cpp]  view plain  copy
  1. void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {  
  2.     uint32_t policyFlags = args->policyFlags;  
  3.     int32_t flags = args->flags;  
  4.     int32_t metaState = args->metaState;  
  5.     if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {  
  6.         policyFlags |= POLICY_FLAG_VIRTUAL;  
  7.         flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;  
  8.     }  
  9.   
  10.     policyFlags |= POLICY_FLAG_TRUSTED;  
  11.   
  12.     KeyEvent event;  
  13.     event.initialize(args->deviceId, args->source, args->action,  
  14.             flags, args->keyCode, args->scanCode, metaState, 0,  
  15.             args->downTime, args->eventTime);  
  16.   
  17.     mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);  
  18.   
  19.     if (policyFlags & POLICY_FLAG_WOKE_HERE) {  
  20.         flags |= AKEY_EVENT_FLAG_WOKE_HERE;  
  21.     }  
  22.   
  23.     bool needWake;  
  24.     { // acquire lock  
  25.         mLock.lock();  
  26.   
  27.         if (shouldSendKeyToInputFilterLocked(args)) {  
  28.             mLock.unlock();  
  29.   
  30.             policyFlags |= POLICY_FLAG_FILTERED;  
  31.             if (!mPolicy->filterInputEvent(&event, policyFlags)) {  
  32.                 return// event was consumed by the filter  
  33.             }  
  34.   
  35.             mLock.lock();  
  36.         }  
  37.   
  38.         int32_t repeatCount = 0;  
  39.         KeyEntry* newEntry = new KeyEntry(args->eventTime,  
  40.                 args->deviceId, args->source, policyFlags,  
  41.                 args->action, flags, args->keyCode, args->scanCode,  
  42.                 metaState, repeatCount, args->downTime);  
  43.   
  44.         needWake = enqueueInboundEventLocked(newEntry);  
  45.         mLock.unlock();  
  46.     } // release lock  
  47.   
  48.     if (needWake) {  
  49.         mLooper->wake();  
  50.     }  
  51. }  

notifyKey函数中首先调用NativeInputManager的interceptKeyBeforeQueueing做提前处理,这里主要是截取一些系统key发送给相应的service处理(例如power key)。然后再构造KeyEntry对象并添加到mInboundQueue中:
[cpp]  view plain  copy
  1. void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,  
  2.         uint32_t& policyFlags) {  
  3.     if ((policyFlags & POLICY_FLAG_TRUSTED)) {  
  4.         nsecs_t when = keyEvent->getEventTime();  
  5.         bool isScreenOn = this->isScreenOn();  
  6.         bool isScreenBright = this->isScreenBright();  
  7.   
  8.         JNIEnv* env = jniEnv();  
  9.         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);  
  10.         jint wmActions;  
  11.         if (keyEventObj) {  
  12.             wmActions = env->CallIntMethod(mServiceObj,  
  13.                     gServiceClassInfo.interceptKeyBeforeQueueing,  
  14.                     keyEventObj, policyFlags, isScreenOn);  
  15.             if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {  
  16.                 wmActions = 0;  
  17.             }  
  18.             android_view_KeyEvent_recycle(env, keyEventObj);  
  19.             env->DeleteLocalRef(keyEventObj);  
  20.         } else {  
  21.   
  22.         }  
  23.   
  24.         if (!(policyFlags & POLICY_FLAG_INJECTED)) {  
  25.             if (!isScreenOn) {  
  26.                 policyFlags |= POLICY_FLAG_WOKE_HERE;  
  27.             }  
  28.   
  29.             if (!isScreenBright) {  
  30.                 policyFlags |= POLICY_FLAG_BRIGHT_HERE;  
  31.             }  
  32.         }  
  33.   
  34.         handleInterceptActions(wmActions, when, /*byref*/ policyFlags);  
  35.     } else {  
  36.         policyFlags |= POLICY_FLAG_PASS_TO_USER;  
  37.     }  
  38. }  

interceptKeyBeforeQueueing首先通过Native的KeyEvent对象构造一个Java层的KeyEvent对象,然后调用InputManagerService的interceptKeyBeforeQueueing去通知WMS相应的input事件:

[java]  view plain  copy
  1. private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {  
  2.     return mWindowManagerCallbacks.interceptKeyBeforeQueueing(  
  3.             event, policyFlags, isScreenOn);  
  4. }  
  5.   
  6. public int interceptKeyBeforeQueueing(  
  7.         KeyEvent event, int policyFlags, boolean isScreenOn) {  
  8.     return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);  
  9. }  

这里的mService.mPolicy是一个PhoneWindowManager对象,我们来看它的interceptKeyBeforeQueueing方法:
[java]  view plain  copy
  1. public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {  
  2.     final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;  
  3.     final boolean canceled = event.isCanceled();  
  4.     final int keyCode = event.getKeyCode();  
  5.   
  6.     final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;  
  7.   
  8.     if (keyCode == KeyEvent.KEYCODE_POWER) {  
  9.         policyFlags |= WindowManagerPolicy.FLAG_WAKE;  
  10.     }  
  11.     final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE  
  12.             | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;  
  13.   
  14.     int result;  
  15.     if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {  
  16.         result = ACTION_PASS_TO_USER;  
  17.     } else {  
  18.         result = 0;  
  19.         if (down && isWakeKey && isWakeKeyWhenScreenOff(keyCode)) {  
  20.             result |= ACTION_WAKE_UP;  
  21.         }  
  22.     }  
  23.   
  24.     switch (keyCode) {  
  25.         case KeyEvent.KEYCODE_POWER: {  
  26.             result &= ~ACTION_PASS_TO_USER;  
  27.             if (down) {  
  28.   
  29.             }  
  30.             else {  
  31.                 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {  
  32.                     result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;  
  33.                 }  
  34.                 mPendingPowerKeyUpCanceled = false;  
  35.             }  
  36.             break;  
  37.         }  
  38.     return result;  
  39. }  



这里需要注意的是,对于power key,如果当前不处于screen on会设置ACTION_WAKE_UP;如果当前处于screen on,在power key松开时会设置ACTION_GO_TO_SLEEP;并且result在不会存在ACTION_PASS_TO_USER这个flag,这个flag表示是否需要将这个event上传给用户。回到NativeInputManager的interceptKeyBeforeQueueing,最后调用handleInterceptActions来处理:
[java]  view plain  copy
  1. void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,  
  2.         uint32_t& policyFlags) {  
  3.     if (wmActions & WM_ACTION_GO_TO_SLEEP) {  
  4.         android_server_PowerManagerService_goToSleep(when);  
  5.     }  
  6.   
  7.     if (wmActions & WM_ACTION_WAKE_UP) {  
  8.         android_server_PowerManagerService_wakeUp(when);  
  9.     }  
  10.   
  11.     if (wmActions & WM_ACTION_PASS_TO_USER) {  
  12.         policyFlags |= POLICY_FLAG_PASS_TO_USER;  
  13.     } else {  
  14.   
  15.     }  
  16. }  

这里会根据PhoneWindowManager的处理结果wmActions来设置来调用不同的处理函数。假设这是处于黑屏状态,就会调用android_server_PowerManagerService_wakeUp去调用PowerManagerService去点亮屏幕;如果当前是screen on状态,这里会调用android_server_PowerManagerService_goToSleep去让手机待机。关于PMS的这两个函数,我们这里就不介绍了。

当dispatchOnceInnerLocked从mInboundQueue取出这个KeyEntry后,会判断它的policyFlags中没有POLICY_FLAG_PASS_TO_USER这个flag,就会把这个event丢弃掉。到这里power key的按下流程就介绍完了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值