4.inputdispatcher的功能
既然事件已经从硬件上读取出来了,那么现在其实需要的就是将这个事件发送给对应的接收者处理。那先来看看inputdispatcher吧。
202InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
203 mPolicy(policy),
204 mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
205 mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
206 mNextUnblockedEvent(NULL),
207 mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
208 mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
209 mLooper = new Looper(false);//注意此处是一个新的looper
210
211 mKeyRepeatState.lastKeyEntry = NULL;
212
213 policy->getDispatcherConfiguration(&mConfig);
214}
那我们接着上篇的inputreader将事件封装后,传递了过来,调用了notifykey
2388void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
//重新封装初始化key
2442 KeyEvent event;
2443 event.initialize(args->deviceId, args->source, args->action,
2444 flags, keyCode, args->scanCode, metaState, 0,
2445 args->downTime, args->eventTime);
2446
2447 mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
2448
//查看是否需要wake这个looper
2474 if (needWake) {
2475 mLooper->wake();
2476 }
2477}
这里可以看到,事件传递上来后,需要先进行policy的一次过滤,这个policy就是当时我们传进去的nativeinputmanager
985void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
986 uint32_t& policyFlags) {
987 ATRACE_CALL();
988 // Policy:
989 // - Ignore untrusted events and pass them along.
990 // - Ask the window manager what to do with normal events and trusted injected events.
991 // - For normal events wake and brighten the screen if currently off or dim.
//备注解释的特别清楚了
1001 if (keyEventObj) {
//通过jni的方式回调java层
1002 wmActions = env->CallIntMethod(mServiceObj,
1003 gServiceClassInfo.interceptKeyBeforeQueueing,
1004 keyEventObj, policyFlags);
1005 if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
1006 wmActions = 0;
1007 }
1008 android_view_KeyEvent_recycle(env, keyEventObj);
1009 env->DeleteLocalRef(keyEventObj);
1010 } else {
1011 ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
1012 wmActions = 0;
1013 }
1021}
回调java层的函数,这时候回到java层
1970 private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1971 return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
1972 }
可以看到,这里其实是掉了当时设置的callback的interceptkeybeforequeue。那当时的callback是啥呢。
当时设置的wm.getinputmonitor,这个inputmonitor是新建出来的,那么
446 @Override
447 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
448 if(mService.mTestFlag){
449 return 0x00000001;
450 }else {
451 return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
452 }
453 }
可以看到又回传到了policy,于是再次回到wms,此处的policy是在新建的时候传入的,查看新建的时候。
896 wm = WindowManagerService.main(context, inputManager,
897 mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
898 !mFirstBoot, mOnlyCore, new PhoneWindowManager());
所以也就是新建的phonewindowmanager。此处也就解释了,为什么有些点击事件是不会传给应用的,而是在phonewindowmanager那里就已经被拦截了。phonewindowmanager里面的一系列策略就不说了,只是会回传结果是是否需要发送给用户。此时回到inputdispatcher,
408bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
409 bool needWake = mInboundQueue.isEmpty();
410 mInboundQueue.enqueueAtTail(entry);
//此处可以看到,一开始就已经把这个事件放进了队列中
464
465 return needWake;
466}
在确认了是否需要wake后,如果需要wake,那么就wake了当前的looper。会调用dispatchonce。
230void InputDispatcher::dispatchOnce() {
231 nsecs_t nextWakeupTime = LONG_LONG_MAX;
232 { // acquire lock
233 AutoMutex _l(mLock);
234 mDispatcherIsAliveCondition.broadcast();
235
236 // Run a dispatch loop if there are no pending commands.
237 // The dispatch loop might enqueue commands to run afterwards.
238 if (!haveCommandsLocked()) {
239 dispatchOnceInnerLocked(&nextWakeupTime);//在此处进行了dispatch操作
240 }
241
242 // Run all pending commands if there are any.
243 // If any commands were run then force the next poll to wake up immediately.
244 if (runCommandsLockedInterruptible()) {
245 nextWakeupTime = LONG_LONG_MIN;
246 }
247 } // release lock
248
249 // Wait for callback or timeout or wake. (make sure we round up, not down)
250 nsecs_t currentTime = now();
251 int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
252 mLooper->pollOnce(timeoutMillis);
253}
看到这里,应该就知道中间的dispatchoneceinner方法就是dispatch的方法了
255void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
280
281 // Ready to start a new event.
282 // If we don't already have a pending event, go grab one.
283 if (! mPendingEvent) {
284 if (mInboundQueue.isEmpty()) {
285 if (isAppSwitchDue) {
286 // The inbound queue is empty so the app switch key we were waiting
287 // for will never arrive. Stop waiting for it.
288 resetPendingAppSwitchLocked(false);
289 isAppSwitchDue = false;
290 }
291
292 // Synthesize a key repeat if appropriate.
293 if (mKeyRepeatState.lastKeyEntry) {
294 if (currentTime >= mKeyRepeatState.nextRepeatTime) {
//如果当前没有事件的话,就从queue中取出一个
295 mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
296 } else {
297 if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
298 *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
299 }
300 }
301 }
302
303 // Nothing to do if there is no pending event.
304 if (!mPendingEvent) {
305 return;
306 }
307 } else {
//如果有的话就直接取出来
308 // Inbound queue has at least one entry.
309 mPendingEvent = mInboundQueue.dequeueAtHead();
310 traceInboundQueueLengthLocked();
311 }
322 // Now we have an event to dispatch.
323 // All events are eventually dequeued and processed this way, even if we intend to drop them.
324 ALOG_ASSERT(mPendingEvent != NULL);
325 bool done = false;
326 DropReason dropReason = DROP_REASON_NOT_DROPPED;
327 if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
328 dropReason = DROP_REASON_POLICY;
329 } else if (!mDispatchEnabled) {
330 dropReason = DROP_REASON_DISABLED;
331 }
332
333 if (mNextUnblockedEvent == mPendingEvent) {
334 mNextUnblockedEvent = NULL;
335 }
336
//对不同事件的处理
337 switch (mPendingEvent->type) {
338 case EventEntry::TYPE_CONFIGURATION_CHANGED: {
339 ConfigurationChangedEntry* typedEntry =
340 static_cast<ConfigurationChangedEntry*>(mPendingEvent);
341 done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
342 dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
343 break;
344 }
345
346 case EventEntry::TYPE_DEVICE_RESET: {
347 DeviceResetEntry* typedEntry =
348 static_cast<DeviceResetEntry*>(mPendingEvent);
349 done = dispatchDeviceResetLocked(currentTime, typedEntry);
350 dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
351 break;
352 }
353
354 case EventEntry::TYPE_KEY: {
355 KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
356 if (isAppSwitchDue) {
357 if (isAppSwitchKeyEventLocked(typedEntry)) {
358 resetPendingAppSwitchLocked(true);
359 isAppSwitchDue = false;
360 } else if (dropReason == DROP_REASON_NOT_DROPPED) {
361 dropReason = DROP_REASON_APP_SWITCH;
362 }
363 }
364 if (dropReason == DROP_REASON_NOT_DROPPED
365 && isStaleEventLocked(currentTime, typedEntry)) {
366 dropReason = DROP_REASON_STALE;
367 }
368 if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
369 dropReason = DROP_REASON_BLOCKED;
370 }
//将事件传递出去
371 done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
372 break;
373 }
374
375 case EventEntry::TYPE_MOTION: {
376 MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
377 if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
378 dropReason = DROP_REASON_APP_SWITCH;
379 }
380 if (dropReason == DROP_REASON_NOT_DROPPED
381 && isStaleEventLocked(currentTime, typedEntry)) {
382 dropReason = DROP_REASON_STALE;
383 }
384 if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
385 dropReason = DROP_REASON_BLOCKED;
386 }
387 done = dispatchMotionLocked(currentTime, typedEntry,
388 &dropReason, nextWakeupTime);
389 break;
390 }
406}
从上面的代码可以看出,可以取出刚刚放进queue中的事件进行处理,那么究竟是怎么处理的呢。
714bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
715 DropReason* dropReason, nsecs_t* nextWakeupTime) {
807 // Dispatch the key.
808 dispatchEventLocked(currentTime, entry, inputTargets);
809 return true;
810}
然后,经过了一系列的逻辑之后,重重判断,这时候终于可以将key dispatch出去了
918void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
919 EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
920#if DEBUG_DISPATCH_CYCLE
921 ALOGD("dispatchEventToCurrentInputTargets");
922#endif
923
924 ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
925
926 pokeUserActivityLocked(eventEntry);
927
928 for (size_t i = 0; i < inputTargets.size(); i++) {
929 const InputTarget& inputTarget = inputTargets.itemAt(i);
930
931 ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
932 if (connectionIndex >= 0) {
933 sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
934 prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
935 } else {
936#if DEBUG_FOCUS
937 ALOGD("Dropping event delivery to target with channel '%s' because it "
938 "is no longer registered with the input dispatcher.",
939 inputTarget.inputChannel->getName().string());
940#endif
941 }
942 }
943}
得到inputtarget的inputchannel,然后发送给对应的channel。
到此为止,input事件的读取和传递就已经告一段落了。
简单梳理下就是ims创建native的ims,nativeims创建inputreader和inputdispatcher,inputreader从eventhub中读取事件,同时将事件传递给inputdispatcher,inputdispatcher再将时间分发出去。
UML时序图如图