AndroidInputSystem

文章以Android 12为例介绍 IMS ->InputManagerService WMS->WindowManagerService

1. 启动流程

InputManagerService是作为系统服务由SystemServer启动的,做为其他服务启动的

/frameworks/base/services/java/com/android/server/SystemServer.java
1248              t.traceBegin("StartInputManagerService");
1249              inputManager = new InputManagerService(context);
1250              t.traceEnd();
1251
1252              t.traceBegin("StartWindowManagerService");
1253              // WMS needs sensor service ready
1254              ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
1255              mSensorServiceStart = null;
1256              wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
1257                      new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
1258              ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
1259                      DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
1260              ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
1261                      /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
1262              t.traceEnd();...
1288              t.traceBegin("StartInputManager");
1289              inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
1290              inputManager.start();
1291              t.traceEnd();

从上面可以看到IMS和WMS有密切的联系,先看一下InputManagerService的构造函数:

1.1 InputManagerService的构造函数

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
325      public InputManagerService(Context context) {326          this.mContext = context;//创建DisplayThread的handler对象,这意味着可以将消息发送给DisplayThread并在DisplayThread中做一些工作
327          this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
328
329          mStaticAssociations = loadStaticInputPortAssociations();
330          mUseDevInputEventForAudioJack =
331                  context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
332          Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
333                  + mUseDevInputEventForAudioJack);//重要的初始化的动作 传入了DisplayThread的Queue
334          mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
335
336          String doubleTouchGestureEnablePath = context.getResources().getString(
337                  R.string.config_doubleTouchGestureEnableFile);
338          mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
339              new File(doubleTouchGestureEnablePath);
340
341          LocalServices.addService(InputManagerInternal.class, new LocalService());
342      }

1.1.1 nativeInit

/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
1265  static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
1266          jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
1267      sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
1268      if (messageQueue == nullptr) {
1269          jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1270          return 0;
1271      }
1272      //新建一个NativeInputManager对象并返回给java层,java层会将其回传给native层来做各种函数调用,serviceObj即是java层的IMS
1273      NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
1274              messageQueue->getLooper());
1275      im->incStrong(0);
1276      return reinterpret_cast<jlong>(im);
1277  }327  NativeInputManager::NativeInputManager(jobject contextObj,
328          jobject serviceObj, const sp<Looper>& looper) :
329          mLooper(looper), mInteractive(true) {
330      JNIEnv* env = jniEnv();
331
332      mServiceObj = env->NewGlobalRef(serviceObj);
333
334      {
335          AutoMutex _l(mLock);
336          mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
337          mLocked.pointerSpeed = 0;
338          mLocked.pointerGesturesEnabled = true;
339          mLocked.showTouches = false;
340          mLocked.pointerCapture = false;
341          mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
342      }
343      mInteractive = true;
344      //NativeInputManager继承了InputReaderPolicyInterface和InputDispatcherPolicyInterface
345      mInputManager = new InputManager(this, this);
346      defaultServiceManager()->addService(String16("inputflinger"),
347              mInputManager, false);
348  }
/frameworks/native/services/inputflinger/InputManager.cpp
34  InputManager::InputManager(
35          const sp<InputReaderPolicyInterface>& readerPolicy,
36          const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
37      mDispatcher = createInputDispatcher(dispatcherPolicy);
38      mClassifier = new InputClassifier(mDispatcher);//InputReader将持有InputDispatcher的引用
39      mReader = createInputReader(readerPolicy, mClassifier);
40  }

上面可以看到input的事件读取和分发都是在InputManager中初始化完成的下面分别看这两个重要的对象初始化的过程

1.1.2 InputDispatcher

/frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
22  sp<InputDispatcherInterface> createInputDispatcher(
23          const sp<InputDispatcherPolicyInterface>& policy) {
24      return new android::inputdispatcher::InputDispatcher(policy);
25  }/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
393  InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
394        : mPolicy(policy),
395          mPendingEvent(nullptr),
396          mLastDropReason(DropReason::NOT_DROPPED),
397          mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
398          mAppSwitchSawKeyDown(false),
399          mAppSwitchDueTime(LONG_LONG_MAX),
400          mNextUnblockedEvent(nullptr),
401          mDispatchEnabled(false),
402          mDispatchFrozen(false),
403          mInputFilterEnabled(false),
404          // mInTouchMode will be initialized by the WindowManager to the default device config.
405          // To avoid leaking stack in case that call never comes, and for tests,
406          // initialize it here anyways.
407          mInTouchMode(true),
408          mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {//创建自己线程的looper对象
409      mLooper = new Looper(false);
410      mReporter = createInputReporter();
411
412      mKeyRepeatState.lastKeyEntry = nullptr;
413      //通过NativeInputManager从上层IMS中获取超时参数keyRepeatTimeout=500 keyRepeatDelay=50
414      policy->getDispatcherConfiguration(&mConfig);
415  }

1.1.3 InputReader

/frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
23  sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
24                                             const sp<InputListenerInterface>& listener) {
25      return new InputReader(std::make_unique<EventHub>(), policy, listener);
26  }
/frameworks/native/services/inputflinger/reader/InputReader.cpp
43  InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
44                           const sp<InputReaderPolicyInterface>& policy,
45                           const sp<InputListenerInterface>& listener)
46        : mContext(this),
47          mEventHub(eventHub),
48          mPolicy(policy),
49          mGlobalMetaState(0),
50          mGeneration(1),
51          mNextInputDeviceId(END_RESERVED_ID),
52          mDisableVirtualKeysTimeout(LLONG_MIN),
53          mNextTimeout(LLONG_MAX),
54          mConfigurationChangesToRefresh(0) {// 创建输入监听对象
55      mQueuedListener = new QueuedInputListener(listener);
56
57      { // acquire lock
58          AutoMutex _l(mLock);
59
60          refreshConfigurationLocked(0);
61          updateGlobalMetaStateLocked();
62      } // release lock
63  }
64

InputReader接受InputDispatcher作为QueuedInputListener来构建监听对象这样读取到事件后可以将其给InputDispatcher去分发,EventHub则是在InputReader的初始化时构建并传入的

1.2 IMS.start

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
352      public void start() {353          Slog.i(TAG, "Starting input manager");
354          nativeStart(mPtr);
355
356          // Add ourself to the Watchdog monitors.
357          Watchdog.getInstance().addMonitor(this);
358
359          registerPointerSpeedSettingObserver();
360          registerShowTouchesSettingObserver();
361          registerAccessibilityLargePointerSettingObserver();
362          registerLongPressTimeoutObserver();
363
364          mContext.registerReceiver(new BroadcastReceiver() {365              @Override
366              public void onReceive(Context context, Intent intent) {367                  updatePointerSpeedFromSettings();
368                  updateShowTouchesFromSettings();
369                  updateAccessibilityLargePointerFromSettings();
370                  updateDeepPressStatusFromSettings("user switched");
371              }
372          }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
373
374          updatePointerSpeedFromSettings();
375          updateShowTouchesFromSettings();
376          updateAccessibilityLargePointerFromSettings();
377          updateDeepPressStatusFromSettings("just booted");
378      }

IMS的start函数则会启动InputManagerService主要做了一下几件事:

1.调用nativeStart启动InputDispatcher和InputReader这两个native线程

2.将自身加入Watchdog的监控

3.注册Setting数据库的观察者,主要关注触摸点速度,是否显示触摸点,大指针设置,和长按超时等数据的变化

4.注册监听User切换的广播接收者

5.从Setting中更新数据

1.2.1 nativeStart

 /frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
1279  static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
1280      NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1281
1282      status_t result = im->getInputManager()->start();
1283      if (result) {
1284          jniThrowRuntimeException(env, "Input manager could not be started.");
1285      }
1286  }
/frameworks/native/services/inputflinger/InputManager.cpp
46  status_t InputManager::start() {
47      status_t result = mDispatcher->start();
48      if (result) {
49          ALOGE("Could not start InputDispatcher thread due to error %d.", result);
50          return result;
51      }
52
53      result = mReader->start();
54      if (result) {
55          ALOGE("Could not start InputReader due to error %d.", result);
56
57          mDispatcher->stop();
58          return result;
59      }
60
61      return OK;
62  }
/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
432  status_t InputDispatcher::start() {
433      if (mThread) {
434          return ALREADY_EXISTS;
435      }
436      mThread = std::make_unique<InputThread>(
437              "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
438      return OK;
439  }
/frameworks/native/services/inputflinger/reader/InputReader.cpp
7  status_t InputReader::start() {
68      if (mThread) {
69          return ALREADY_EXISTS;
70      }
71      mThread = std::make_unique<InputThread>(
72              "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
73      return OK;
74  }

InputDispatcher的工作时由他自己的Loope唤醒的,而InputReader则是由mEventHub唤醒的.

system_server进程中有三个线程和input系统相关,分别时DisplayThread,InputDispatcher和InputReader

  • InputDispatcher线程:属于Looper线程,会创建属于自己的Looper,循环分发消息;
  • InputReader线程:通过getEvents()调用EventHub读取输入事件,循环读取消息;
  • android.display线程:属于Looper线程,用于处理Java层的IMS.InputManagerHandler和JNI层的NativeInputManager中指定的MessageHandler消息;

Input事件流程:Linux Kernel -> IMS(InputReader -> InputDispatcher) -> WMS -> ViewRootImpl.

1.2.2 InputThread线程

由启动流程可以知道InputReader线程和InputDispatcher线程的启动是新建了InputThread对象

/frameworks/native/services/inputflinger/InputThread.cpp
42  InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
43        : mName(name), mThreadWake(wake) {
44      mThread = new InputThreadImpl(loop);
45      mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
46  }

InputThread继承于Thread是一个线程类当执行run后就是执行threadLoop函数并根据返回值决定是循环执行还是只执行一次。

/system/core/libutils/include/utils/Thread.h
49      // Start the thread in threadLoop() which needs to be implemented.
50      // NOLINTNEXTLINE(google-default-arguments)
51      virtual status_t    run(    const char* name,
52                                  int32_t priority = PRIORITY_DEFAULT,
53                                  size_t stack = 0);
87      // Derived class must implement threadLoop(). The thread starts its life
88      // here. There are two ways of using the Thread object:
89      // 1) loop: if threadLoop() returns true, it will be called again if
90      //          requestExit() wasn't called.
91      // 2) once: if threadLoop() returns false, the thread will exit upon return.
92      virtual bool        threadLoop() = 0;

2. InputReader线程

当InputThread启动后会执行ThreadLoop函数,而threadLoop函数是InputReader传入的loopOnce。

/frameworks/native/services/inputflinger/reader/InputReader.cpp
85  void InputReader::loopOnce() {
86      int32_t oldGeneration;
87      int32_t timeoutMillis;
88      bool inputDevicesChanged = false;
89      std::vector<InputDeviceInfo> inputDevices;
90      { // acquire lock
91          AutoMutex _l(mLock);
92
93          oldGeneration = mGeneration;
94          timeoutMillis = -1;
95
96          uint32_t changes = mConfigurationChangesToRefresh;
97          if (changes) {
98              mConfigurationChangesToRefresh = 0;
99              timeoutMillis = 0;
100              refreshConfigurationLocked(changes);
101          } else if (mNextTimeout != LLONG_MAX) {
102              nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
103              timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
104          }
105      } // release lock
106      //从EventHub读取输入事件 事件放入mEventBuffer EVENT_BUFFER_SIZE = 256
107      size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
108
109      { // acquire lock
110          AutoMutex _l(mLock);
111          mReaderIsAliveCondition.broadcast();
112
113          if (count) {//处理输入事件
114              processEventsLocked(mEventBuffer, count);
115          }
116
117          if (mNextTimeout != LLONG_MAX) {
118              nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
119              if (now >= mNextTimeout) {
120  #if DEBUG_RAW_EVENTS
121                  ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
122  #endif
123                  mNextTimeout = LLONG_MAX;
124                  timeoutExpiredLocked(now);
125              }
126          }
127          //输入设备发生改变
128          if (oldGeneration != mGeneration) {
129              inputDevicesChanged = true;
130              getInputDevicesLocked(inputDevices);
131          }
132      } // release lock
133
134      // Send out a message that the describes the changed input devices.
135      if (inputDevicesChanged) {
136          mPolicy->notifyInputDevicesChanged(inputDevices);
137      }
138
139      // Flush queued events out to the listener.
140      // This must happen outside of the lock because the listener could potentially call
141      // back into the InputReader's methods, such as getScanCodeState, or become blocked
142      // on another thread similarly waiting to acquire the InputReader lock thereby
143      // resulting in a deadlock.  This situation is actually quite plausible because the
144      // listener is actually the input dispatcher, which calls into the window manager,
145      // which occasionally calls into the input reader.//使用mQueuedListener发送事件到InputDispatcher
146      mQueuedListener->flush();
147  }

可以看到InputReader线程主要是三方面的工作1.读取事件 2.处理事件 3发送事件给InputDispatcher

2.1 读取事件

InputReader读取事件使用的是EventHub.getEvent()

/frameworks/native/services/inputflinger/reader/EventHub.cpp
847  size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
848      ALOG_ASSERT(bufferSize >= 1);
849
850      AutoMutex _l(mLock);
851
852      struct input_event readBuffer[bufferSize];
853
854      RawEvent* event = buffer; //InputReader传入放输入事件的buffer
855      size_t capacity = bufferSize; //buffer size为256
856      bool awoken = false;
857      for (;;) {  //循环等待
858          nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
859           //要重新打开InputDevice,会先关闭所有的InputDevice,同时把mNeedToScanDevices置为true
860          // Reopen input devices if needed.
861          if (mNeedToReopenDevices) {
862              mNeedToReopenDevices = false;
864              ALOGI("Reopening all input devices due to a configuration change.");
866              closeAllDevicesLocked();
867              mNeedToScanDevices = true;
868              break; // return to the caller before we actually rescan
869          }
870
871          // Report any devices that had last been added/removed.
872          while (mClosingDevices) {
873              Device* device = mClosingDevices;
874              ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
875              mClosingDevices = device->next;
876              event->when = now;
877              event->deviceId = (device->id == mBuiltInKeyboardId)
878                      ? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
879                      : device->id;
880              event->type = DEVICE_REMOVED;//inputDevice移除事件
881              event += 1;
882              delete device;
883              mNeedToSendFinishedDeviceScan = true;
884              if (--capacity == 0) {
885                  break;
886              }
887          }
888
889          if (mNeedToScanDevices) {
890              mNeedToScanDevices = false;
891              scanDevicesLocked(); //重新扫描inputdevice
892              mNeedToSendFinishedDeviceScan = true;
893          }
894          //report哪些inputdevice被打开了
895          while (mOpeningDevices != nullptr) {
896              Device* device = mOpeningDevices;
897              ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
898              mOpeningDevices = device->next;
899              event->when = now;
900              event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
901              event->type = DEVICE_ADDED;  //inputDevice添加事件
902              event += 1;
903              mNeedToSendFinishedDeviceScan = true;
904              if (--capacity == 0) {
905                  break;
906              }
907          }
908
909          if (mNeedToSendFinishedDeviceScan) {
910              mNeedToSendFinishedDeviceScan = false;
911              event->when = now;
912              event->type = FINISHED_DEVICE_SCAN;//inputDevice完成扫描的事件
913              event += 1;
914              if (--capacity == 0) {
915                  break;
916              }
917          }
918           //获取下一个input事件
919          // Grab the next input event.
920          bool deviceChanged = false;
921          while (mPendingEventIndex < mPendingEventCount) {
922              const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
923              if (eventItem.data.fd == mINotifyFd) {
924                  ...
929                  continue;
930              }
931              //唤醒InputReader的事件
932              if (eventItem.data.fd == mWakeReadPipeFd) {
933                  if (eventItem.events & EPOLLIN) {
934                      ALOGV("awoken after wake()");
935                      awoken = true;
936                      char buffer[16];
937                      ssize_t nRead;
938                      do {
939                          nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
940                      } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
941                  } else {
942                      ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
943                            eventItem.events);
944                  }
945                  continue;
946              }
947              //通过devicefd获取到事件对应的device
948              Device* device = getDeviceByFdLocked(eventItem.data.fd);
949              if (!device) {
950                  ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
951                        eventItem.data.fd);
952                  ALOG_ASSERT(!DEBUG);
953                  continue;
954              }//videoDevice的事件
955              if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
956                  ...
973                  continue;
974              }
975              // This must be an input event 普通的input事件
976              if (eventItem.events & EPOLLIN) {//调用read从device中读取事件放入到readBuffer中 返回读取事件的大小
977                  int32_t readSize =
978                          read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
979                  if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
980                      // Device was removed before INotify noticed.
981                      ALOGW("could not get event, removed? (fd: %d size: %" PRId32
982                            " bufferSize: %zu capacity: %zu errno: %d)\n",
983                            device->fd, readSize, bufferSize, capacity, errno);
984                      deviceChanged = true;
985                      closeDeviceLocked(device); //设备已经移除,执行关闭操作
986                  } else if (readSize < 0) {//没有读取到事件
987                      if (errno != EAGAIN && errno != EINTR) {
988                          ALOGW("could not get event (errno=%d)", errno);
989                      }
990                  } else if ((readSize % sizeof(struct input_event)) != 0) {//读取到的事件大小出错
991                      ALOGE("could not get event (wrong size: %d)", readSize);
992                  } else {//将读出的事件全部包装成RawEvent事件
993                      int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
994
995                      size_t count = size_t(readSize) / sizeof(struct input_event);
996                      for (size_t i = 0; i < count; i++) {
997                          struct input_event& iev = readBuffer[i];
998                          event->when = processEventTimestamp(iev);
999                          event->deviceId = deviceId;
1000                          event->type = iev.type;
1001                          event->code = iev.code;
1002                          event->value = iev.value;
1003                          event += 1;
1004                          capacity -= 1;
1005                      }
1006                      if (capacity == 0) {
1007                          // The result buffer is full.  Reset the pending event index
1008                          // so we will try to read the device again on the next iteration.
1009                          mPendingEventIndex -= 1;
1010                          break;
1011                      }
1012                  }
1013              } else if (eventItem.events & EPOLLHUP) {//设备被移除
1014                  ALOGI("Removing device %s due to epoll hang-up event.",
1015                        device->identifier.name.c_str());
1016                  deviceChanged = true;
1017                  closeDeviceLocked(device);
1018              } else {
1019                  ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
1020                        device->identifier.name.c_str());
1021              }
1022          }
1023
1024          // readNotify() will modify the list of devices so this must be done after
1025          // processing all other events to ensure that we read all remaining events
1026          // before closing the devices.
1027          if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
1028              mPendingINotify = false;
1029              readNotifyLocked();
1030              deviceChanged = true;
1031          }
1032
1033          // Report added or removed devices immediately.
1034          if (deviceChanged) {
1035              continue;
1036          }
1037
1038          // Return now if we have collected any events or if we were explicitly awoken.
1039          if (event != buffer || awoken) {
1040              break;
1041          }
1042
1043          // Poll for events.
1044          // When a device driver has pending (unread) events, it acquires
1045          // a kernel wake lock.  Once the last pending event has been read, the device
1046          // driver will release the kernel wake lock, but the epoll will hold the wakelock,
1047          // since we are using EPOLLWAKEUP. The wakelock is released by the epoll when epoll_wait
1048          // is called again for the same fd that produced the event.
1049          // Thus the system can only sleep if there are no events pending or
1050          // currently being processed.
1051          //
1052          // The timeout is advisory only.  If the device is asleep, it will not wake just to
1053          // service the timeout.
1054          mPendingEventIndex = 0;
1055
1056          mLock.unlock(); // release lock before poll
1057          等待input事件的到来 EPOLL_MAX_EVENTS 16
1058          int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
1059
1060          mLock.lock(); // reacquire lock after poll
1061
1062          if (pollResult == 0) {
1063              // Timed out.
1064              mPendingEventCount = 0;
1065              break;
1066          }
1067
1068          if (pollResult < 0) {
1069              // An error occurred.
1070              mPendingEventCount = 0;
1071
1072              // Sleep after errors to avoid locking up the system.
1073              // Hopefully the error is transient.
1074              if (errno != EINTR) {
1075                  ALOGW("poll failed (errno=%d)\n", errno);
1076                  usleep(100000);
1077              }
1078          } else {
1079              // Some events occurred.
1080              mPendingEventCount = size_t(pollResult);
1081          }
1082      }
1083
1084      // All done, return the number of events we read.
1085      return event - buffer; //返回所读取的事件个数
1086  }

EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点,经过EventHub将input_event结构体 + deviceId 转换成RawEvent结构体,

  • 节点/dev/input的event事件所对应的输入设备信息位于/proc/bus/input/devices,也可以通过getevent来获取事件. 不同的input事件所对应的物理input节点,比如常见的情形:

    • 屏幕触摸和(MENU,HOME,BACK)3按键:对应同一个input设备节点;
    • POWER和音量(下)键:对应同一个input设备节点;
    • 音量(上)键:对应同一个input设备节点;

2.1.1 扫描Input设备

/frameworks/native/services/inputflinger/reader/EventHub.cpp
72  static const char* DEVICE_PATH = "/dev/input";
73  // v4l2 devices go directly into /dev
74  static const char* VIDEO_DEVICE_PATH = "/dev";
1111  void EventHub::scanDevicesLocked() {//可以看到我们扫描设备时都是扫描/dev/input下面的节点
1112      status_t result = scanDirLocked(DEVICE_PATH);
1113      if (result < 0) {
1114          ALOGE("scan dir failed for %s", DEVICE_PATH);
1115      }
1116      if (isV4lScanningEnabled()) {
1117          result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
1118          if (result != OK) {
1119              ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
1120          }
1121      }
1122      if (mDevices.indexOfKey(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) < 0) { //没有键盘节点需要创建虚拟键盘
1123          createVirtualKeyboardLocked();
1124      }
1125  }
1866  status_t EventHub::scanDirLocked(const char* dirname) {
1867      char devname[PATH_MAX];
1868      char* filename;
1869      DIR* dir;
1870      struct dirent* de;
1871      dir = opendir(dirname);
1872      if (dir == nullptr) return -1;
1873      strcpy(devname, dirname);
1874      filename = devname + strlen(devname);
1875      *filename++ = '/';///dev/input下面有如下节点: 在AndroidQ的模拟器上event0 event1 event2 event3
1876      while ((de = readdir(dir))) {
1877          if (de->d_name[0] == '.' &&
1878              (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
1879              continue;
1880          strcpy(filename, de->d_name);//打开设备节点
1881          openDeviceLocked(devname);
1882      }
1883      closedir(dir);
1884      return 0;
1885  }1218  status_t EventHub::openDeviceLocked(const char* devicePath) {
1219      char buffer[80];
1220
1221      ALOGV("Opening device: %s", devicePath);
1222      //打开设备文件
1223      int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
1224      if (fd < 0) {
1225          ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
1226          return -1;
1227      }
1228
1229      InputDeviceIdentifier identifier;
1230      //获取设备的名字 ioctl时一个用户空间的函数最终和驱动程序打交道
1231      // Get device name.
1232      if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
1233          ALOGE("Could not get device name for %s: %s", devicePath, strerror(errno));
1234      } else {
1235          buffer[sizeof(buffer) - 1] = '\0';
1236          identifier.name = buffer;
1237      }
1238      //检查设备是否在排除的范围  可以在etc/excluded-input-devices.xml中配置需要无视的Input设备
1239      // Check to see if the device is on our excluded list
1240      for (size_t i = 0; i < mExcludedDevices.size(); i++) {
1241          const std::string& item = mExcludedDevices[i];
1242          if (identifier.name == item) {
1243              ALOGI("ignoring event id %s driver %s\n", devicePath, item.c_str());
1244              close(fd);
1245              return -1;
1246          }
1247      }
1248      //获取设备驱动的版本
1249      // Get device driver version.
1250      int driverVersion;
1251      if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
1252          ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
1253          close(fd);
1254          return -1;
1255      }
1256      //获取设备的认证id
1257      // Get device identifier.
1258      struct input_id inputId;
1259      if (ioctl(fd, EVIOCGID, &inputId)) {
1260          ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
1261          close(fd);
1262          return -1;
1263      }
1264      identifier.bus = inputId.bustype;
1265      identifier.product = inputId.product;
1266      identifier.vendor = inputId.vendor;
1267      identifier.version = inputId.version;
1268      //获取设备的物理地址
1269      // Get device physical location.
1270      if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
1271          // fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
1272      } else {
1273          buffer[sizeof(buffer) - 1] = '\0';
1274          identifier.location = buffer;
1275      }
1276      //获取设备的唯一id
1277      // Get device unique id.
1278      if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
1279          // fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
1280      } else {
1281          buffer[sizeof(buffer) - 1] = '\0';
1282          identifier.uniqueId = buffer;
1283      }
1284      //将identifier信息填充到fd
1285      // Fill in the descriptor.
1286      assignDescriptorLocked(identifier);
1287       //创建device对象
1288      // Allocate device.  (The device object takes ownership of the fd at this point.)
1289      int32_t deviceId = mNextDeviceId++;
1290      Device* device = new Device(fd, deviceId, devicePath, identifier);
1291
1292      ALOGV("add device %d: %s\n", deviceId, devicePath);
1293      ALOGV("  bus:        %04x\n"
1294            "  vendor      %04x\n"
1295            "  product     %04x\n"
1296            "  version     %04x\n",
1297            identifier.bus, identifier.vendor, identifier.product, identifier.version);
1298      ALOGV("  name:       \"%s\"\n", identifier.name.c_str());
1299      ALOGV("  location:   \"%s\"\n", identifier.location.c_str());
1300      ALOGV("  unique id:  \"%s\"\n", identifier.uniqueId.c_str());
1301      ALOGV("  descriptor: \"%s\"\n", identifier.descriptor.c_str());
1302      ALOGV("  driver:     v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
1303            driverVersion & 0xff);
1304      //为设备加载配置文件
1305      // Load the configuration file for the device.
1306      loadConfigurationLocked(device);
1307       //理解这个device所能报告的事件的类型
1308      // Figure out the kinds of events the device reports.
1309      ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
1310      ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
1311      ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
1312      ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
1313      ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
1314      ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
1315      ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);//各种乱七八糟的设备的确认和配置 如手柄 轨迹球 鼠标 键盘 触摸板等等....//将device的fd注册到epoll中
1486      if (registerDeviceForEpollLocked(device) != OK) {
1487          delete device;
1488          return -1;
1489      }
1490
1491      configureFd(device);
1492
1493      ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
1494            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
1495            deviceId, fd, devicePath, device->identifier.name.c_str(), device->classes,
1496            device->configurationFile.c_str(), device->keyMap.keyLayoutFile.c_str(),
1497            device->keyMap.keyCharacterMapFile.c_str(), toString(mBuiltInKeyboardId == deviceId));
1498
1499      addDeviceLocked(device);
1500      return OK;
1501  }1609  void EventHub::addDeviceLocked(Device* device) {
1610      mDevices.add(device->id, device);
1611      device->next = mOpeningDevices;
1612      mOpeningDevices = device;
1613  }

2.2 处理事件

InputReader处理事件用的是processEventsLocked传入从EventHub获取到的mEventBuffer和count

/frameworks/native/services/inputflinger/reader/InputReader.cpp
149  void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
150      for (const RawEvent* rawEvent = rawEvents; count;) {
151          int32_t type = rawEvent->type;
152          size_t batchSize = 1;
153          if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
154              int32_t deviceId = rawEvent->deviceId;
155              while (batchSize < count) {
156                  if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
157                      rawEvent[batchSize].deviceId != deviceId) {
158                      break;
159                  }
160                  batchSize += 1;
161              }
162  #if DEBUG_RAW_EVENTS
163              ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
164  #endif      //数据事件的处理
165              processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
166          } else {
167              switch (rawEvent->type) {//设备添加事件
168                  case EventHubInterface::DEVICE_ADDED:
169                      addDeviceLocked(rawEvent->when, rawEvent->deviceId);
170                      break;//设备移除事件
171                  case EventHubInterface::DEVICE_REMOVED:
172                      removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
173                      break;//设备扫描完成事件
174                  case EventHubInterface::FINISHED_DEVICE_SCAN:
175                      handleConfigurationChangedLocked(rawEvent->when);
176                      break;
177                  default:
178                      ALOG_ASSERT(false); // can't happen
179                      break;
180              }
181          }
182          count -= batchSize;
183          rawEvent += batchSize;
184      }
185  }

可以看到事件的处理主要是四种 1. 数据事件的处理 2. 设备添加事件 3.设备移除事件 4.设备扫描完成事件

2.2.1 设备添加事件的处理

设备添加事件是由addDeviceLocked处理的传入Event发生的时间和deviceid

/frameworks/native/services/inputflinger/reader/InputReader.cpp
187  void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
188      if (mDevices.find(eventHubId) != mDevices.end()) {
189          ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
190          return;
191      }
192      //通过deviceid获取扫描时建立的identifier
193      InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);//创建InputDevice
194      std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
195      device->configure(when, &mConfig, 0);
196      device->reset(when);
197
198      if (device->isIgnored()) {
199          ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
200                "(ignored non-input device)",
201                device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str());
202      } else {
203          ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=0x%08x",
204                device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),
205                device->getSources());
206      }
207      //将创建的InputDevice以deviceid为索引设置到InputReader中的mDevices中
208      mDevices.emplace(eventHubId, device);
209      // Add device to device to EventHub ids map.//设置device到EventHub id的映射Map
210      const auto mapIt = mDeviceToEventHubIdsMap.find(device);
211      if (mapIt == mDeviceToEventHubIdsMap.end()) {
212          std::vector<int32_t> ids = {eventHubId};
213          mDeviceToEventHubIdsMap.emplace(device, ids);
214      } else {
215          mapIt->second.push_back(eventHubId);
216      }
217      bumpGenerationLocked();
218
219      if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
220          notifyExternalStylusPresenceChanged();
221      }
222  }
269  std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
270          int32_t eventHubId, const InputDeviceIdentifier& identifier) {
271      auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
272          return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&
273                  devicePair.second->getDescriptor() == identifier.descriptor;
274      });
275     //先从mDevices中寻找,找不到新建
276      std::shared_ptr<InputDevice> device;
277      if (deviceIt != mDevices.end()) {
278          device = deviceIt->second;
279      } else {
280          int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
281          device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
282                                                 identifier);
283      }
284      device->addEventHubDevice(eventHubId);
285      return device;
286  }
/frameworks/native/services/inputflinger/reader/InputDevice.cpp
131  void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
132      if (mDevices.find(eventHubId) != mDevices.end()) {
133          return;
134      }
135      std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));//获取输入设备的类型
136      uint32_t classes = contextPtr->getDeviceClasses();
137      std::vector<std::unique_ptr<InputMapper>> mappers;
138
139      // Check if we should skip population
140      if (!populateMappers) {
141          mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
142          return;
143      }
144      // 根据输入设备的类型添加不同的InputMapper
145      // Switch-like devices.
146      if (classes & INPUT_DEVICE_CLASS_SWITCH) {
147          mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
148      }
149
150      // Scroll wheel-like devices.
151      if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
152          mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
153      }
154
155      // Vibrator-like devices.
156      if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
157          mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
158      }
159
160      // Keyboard-like devices.
161      uint32_t keyboardSource = 0;
162      int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
163      if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
164          keyboardSource |= AINPUT_SOURCE_KEYBOARD;
165      }
166      if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
167          keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
168      }
169      if (classes & INPUT_DEVICE_CLASS_DPAD) {
170          keyboardSource |= AINPUT_SOURCE_DPAD;
171      }
172      if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
173          keyboardSource |= AINPUT_SOURCE_GAMEPAD;
174      }
175
176      if (keyboardSource != 0) {
177          mappers.push_back(
178                  std::make_unique<KeyboardInputMapper>(*contextPtr, keyboardSource, keyboardType));
179      }
180
181      // Cursor-like devices.
182      if (classes & INPUT_DEVICE_CLASS_CURSOR) {
183          mappers.push_back(std::make_unique<CursorInputMapper>(*contextPtr));
184      }
185
186      // Touchscreens and touchpad devices.
187      if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
188          mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
189      } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
190          mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
191      }
192
193      // Joystick-like devices.
194      if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
195          mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
196      }
197
198      // External stylus-like devices.
199      if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
200          mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
201      }
202      //把contex插入到devices的set中
203      // insert the context into the devices set
204      mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
205      // Must change generation to flag this device as changed
206      bumpGeneration();
207  }

设备添加事件的处理结果是创建InputDevice并将其加到InputReader中的mDevices中。

2.2.2 设备删除事件的处理

设备删除事件的处理是removeDeviceLocked来实现的

/frameworks/native/services/inputflinger/reader/InputReader.cpp
224  void InputReader::removeDeviceLocked(nsecs_t when, int32_t eventHubId) {
225      auto deviceIt = mDevices.find(eventHubId);
226      if (deviceIt == mDevices.end()) {
227          ALOGW("Ignoring spurious device removed event for eventHubId %d.", eventHubId);
228          return;
229      }
230  //将对应的device从mDevices中移除同时移除device到EventHub id的映射
231      std::shared_ptr<InputDevice> device = std::move(deviceIt->second);
232      mDevices.erase(deviceIt);
233      // Erase device from device to EventHub ids map.
234      auto mapIt = mDeviceToEventHubIdsMap.find(device);
235      if (mapIt != mDeviceToEventHubIdsMap.end()) {
236          std::vector<int32_t>& eventHubIds = mapIt->second;
237          eventHubIds.erase(std::remove_if(eventHubIds.begin(), eventHubIds.end(),
238                                           [eventHubId](int32_t eId) { return eId == eventHubId; }),
239                            eventHubIds.end());
240          if (eventHubIds.size() == 0) {
241              mDeviceToEventHubIdsMap.erase(mapIt);
242          }
243      }
244      bumpGenerationLocked();
245
246      if (device->isIgnored()) {
247          ALOGI("Device removed: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
248                "(ignored non-input device)",
249                device->getId(), eventHubId, device->getName().c_str(),
250                device->getDescriptor().c_str());
251      } else {
252          ALOGI("Device removed: id=%d, eventHubId=%d, name='%s', descriptor='%s', sources=0x%08x",
253                device->getId(), eventHubId, device->getName().c_str(),
254                device->getDescriptor().c_str(), device->getSources());
255      }
256      //调用removeEventHubDevice移除EventHubDevice
257      device->removeEventHubDevice(eventHubId);
258
259      if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
260          notifyExternalStylusPresenceChanged();
261      }
262
263      if (device->hasEventHubDevices()) {
264          device->configure(when, &mConfig, 0);
265      }
266      device->reset(when);
267  }//从mDevices中移除deviceid
209  void InputDevice::removeEventHubDevice(int32_t eventHubId) {
210      mDevices.erase(eventHubId);
211  }

可以看到设备移除和设备添加是相反的过程

2.2.3 设备扫描完成的事件处理

设备扫描完成的事件处理是由handleConfigurationChangedLocked完成的主要是一些配置的改变

 /frameworks/native/services/inputflinger/reader/InputReader.cpp
329  void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
330      // Reset global meta state because it depends on the list of all configured devices.
331      updateGlobalMetaStateLocked();
332
333      // Enqueue configuration changed.
334      NotifyConfigurationChangedArgs args(mContext.getNextId(), when);
335      mQueuedListener->notifyConfigurationChanged(&args);
336  }

2.2.4 数据事件的处理

数据事件即普通的input事件主要是由processEventsForDeviceLocked完成的

/frameworks/native/services/inputflinger/reader/InputReader.cpp
288  void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
289                                                 size_t count) {
290      auto deviceIt = mDevices.find(eventHubId);
291      if (deviceIt == mDevices.end()) {
292          ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
293          return;
294      }
295
296      std::shared_ptr<InputDevice>& device = deviceIt->second;
297      if (device->isIgnored()) {
298          // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
299          return;
300      }
301
302      device->process(rawEvents, count);
303  }
//数据事件处理的主要工作
/frameworks/native/services/inputflinger/reader/InputDevice.cpp
335  void InputDevice::process(const RawEvent* rawEvents, size_t count) {
336      // Process all of the events in order for each mapper.
337      // We cannot simply ask each mapper to process them in bulk because mappers may
338      // have side-effects that must be interleaved.  For example, joystick movement events and
339      // gamepad button presses are handled by different mappers but they should be dispatched
340      // in the order received.
341      for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
342  #if DEBUG_RAW_EVENTS
343          ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
344                rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
345  #endif
346
347          if (mDropUntilNextSync) {
348              if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
349                  mDropUntilNextSync = false;
350  #if DEBUG_RAW_EVENTS
351                  ALOGD("Recovered from input event buffer overrun.");
352  #endif
353              } else {
354  #if DEBUG_RAW_EVENTS
355                  ALOGD("Dropped input event while waiting for next input sync.");
356  #endif
357              }
358          } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
359              ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
360              mDropUntilNextSync = true;
361              reset(rawEvent->when);
362          } else {//调用具体mapper来处理
363              for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
364                  mapper.process(rawEvent);
365              });
366          }
367          --count;
368      }
369  }

这里的mapper就是在设备添加事件中执行device.addEventHubDevice时根据输入设备的类型加进来的各种InputMapper,主要有以下mapper:

SwitchInputMapper,RotaryEncoderInputMapper,VibratorInputMapper,KeyboardInputMapper,CursorInputMapper,TouchInputMapper,
JoystickInputMapper,ExternalStylusInputMapper

关系如图所示:

这里以KeyboardInputMapper为例来看一下是如何处理输入事件的

 /frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
209  void KeyboardInputMapper::process(const RawEvent* rawEvent) {
210      switch (rawEvent->type) {
211          case EV_KEY: {
212              int32_t scanCode = rawEvent->code;
213              int32_t usageCode = mCurrentHidUsage;
214              mCurrentHidUsage = 0;
215              //如果时键盘的key则会走processkey
216              if (isKeyboardOrGamepadKey(scanCode)) {
217                  processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
218              }
219              break;
220          }
221          case EV_MSC: {
222              if (rawEvent->code == MSC_SCAN) {
223                  mCurrentHidUsage = rawEvent->value;
224              }
225              break;
226          }
227          case EV_SYN: {
228              if (rawEvent->code == SYN_REPORT) {
229                  mCurrentHidUsage = 0;
230              }
231          }
232      }
233  }
270  void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode) {
271      int32_t keyCode;
272      int32_t keyMetaState;
273      uint32_t policyFlags;
274      //获取key对应的keycode 根据scanCode(事件扫描码)找到keyCode(键盘码)
275      if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
276                                    &policyFlags)) {
277          keyCode = AKEYCODE_UNKNOWN;
278          keyMetaState = mMetaState;
279          policyFlags = 0;
280      }
281
282      if (down) {
283          // Rotate key codes according to orientation if needed.
284          if (mParameters.orientationAware) {
285              keyCode = rotateKeyCode(keyCode, getOrientation());
286          }
287          //把当前按下的键加入到mKeyDowns中  mKeyDowns记录了所有按下的键
288          // Add key down.
289          ssize_t keyDownIndex = findKeyDown(scanCode);
290          if (keyDownIndex >= 0) {
291              // key repeat, be sure to use same keycode as before in case of rotation
292              keyCode = mKeyDowns[keyDownIndex].keyCode;
293          } else {
294              // key down
295              if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
296                  getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
297                  return;
298              }
299              if (policyFlags & POLICY_FLAG_GESTURE) {
300                  getDeviceContext().cancelTouch(when);
301              }
302
303              KeyDown keyDown;
304              keyDown.keyCode = keyCode;
305              keyDown.scanCode = scanCode;
306              mKeyDowns.push_back(keyDown);
307          }
308          //记录按下的时间
309          mDownTime = when;
310      } else {
311          // Remove key down.
312          ssize_t keyDownIndex = findKeyDown(scanCode);
313          if (keyDownIndex >= 0) {//键抬起操作,则移除按下事件
314              // key up, be sure to use same keycode as before in case of rotation
315              keyCode = mKeyDowns[keyDownIndex].keyCode;
316              mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
317          } else {
318              // key was not actually down
319              ALOGI("Dropping key up from device %s because the key was not down.  "
320                    "keyCode=%d, scanCode=%d",
321                    getDeviceName().c_str(), keyCode, scanCode);
322              return; //键抬起操作,则移除按下事件
323          }
324      }
325
326      if (updateMetaStateIfNeeded(keyCode, down)) {
327          // If global meta state changed send it along with the key.
328          // If it has not changed then we'll use what keymap gave us,
329          // since key replacement logic might temporarily reset a few
330          // meta bits for given key.
331          keyMetaState = mMetaState;
332      }
333
334      nsecs_t downTime = mDownTime;
335
336      // Key down on external an keyboard should wake the device.
337      // We don't do this for internal keyboards to prevent them from waking up in your pocket.
338      // For internal keyboards and devices for which the default wake behavior is explicitly
339      // prevented (e.g. TV remotes), the key layout file should specify the policy flags for each
340      // wake key individually.
341      // TODO: Use the input device configuration to control this behavior more finely.
342      if (down && getDeviceContext().isExternal() && !mParameters.doNotWakeByDefault &&
343          !isMediaKey(keyCode)) {
344          policyFlags |= POLICY_FLAG_WAKE;
345      }
346
347      if (mParameters.handlesKeyRepeat) {
348          policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
349      }
350      //创建NotifyKeyArgs对象, when记录eventTime, downTime记录按下时间
351      NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, getDisplayId(),
352                         policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
353                         AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);//这里的getListener就是InputReader中的 mQueuedListener
354      getListener()->notifyKey(&args);
355  }
/frameworks/native/services/inputflinger/InputListener.cpp
261  void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
262      traceEvent(__func__, args->id);
263      mArgsQueue.push_back(new NotifyKeyArgs(*args));
264  }

2.3 分发事件给InputDispatcher

分发事件使用的是mQueuedListener->flush(),如下:

/frameworks/native/services/inputflinger/InputListener.cpp
281  void QueuedInputListener::flush() {
282      size_t count = mArgsQueue.size();
283      for (size_t i = 0; i < count; i++) {
284          NotifyArgs* args = mArgsQueue[i];
285          args->notify(mInnerListener);
286          delete args;
287      }
288      mArgsQueue.clear();
289  }

上面可以看到分发主要是从mArgsQueue中遍历所有的NotifyArgs* 调用其notify分发事件 mInnerListener为InputDispatcher,NotifyArgs的实现有以下几种

NotifyConfigurationChangedArgs,NotifyKeyArgs,NotifyMotionArgs,NotifySwitchArgs,NotifyDeviceResetArgs。如下图所示:

接着2.2.4可以知道我们关注的是NotifyKeyArgs的notify函数。

/frameworks/native/services/inputflinger/InputListener.cpp
89  void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
90      listener->notifyKey(this);
91  }

在InputReader初始化是将InputDispatcher传入构造了mQueuedListener所以这里的listener即InputDispatcher。最终调用了InputDispatcher的notifyKey

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
3106  void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
3107  #if DEBUG_INBOUND_EVENT_DETAILS
3108      ALOGD("notifyKey - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
3109            "policyFlags=0x%x, action=0x%x, "
3110            "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%" PRId64,
3111            args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
3112            args->action, args->flags, args->keyCode, args->scanCode, args->metaState,
3113            args->downTime);
3114  #endif//check KeyEvent是否有效,只有是 AKEY_EVENT_ACTION_DOWN或者是AKEY_EVENT_ACTION_UP才是有效的keyEvent
3115      if (!validateKeyEvent(args->action)) {
3116          return;
3117      }
3118
3119      uint32_t policyFlags = args->policyFlags;
3120      int32_t flags = args->flags;
3121      int32_t metaState = args->metaState;
3122      // InputDispatcher tracks and generates key repeats on behalf of
3123      // whatever notifies it, so repeatCount should always be set to 0
3124      constexpr int32_t repeatCount = 0;
3125      if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
3126          policyFlags |= POLICY_FLAG_VIRTUAL;
3127          flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
3128      }
3129      if (policyFlags & POLICY_FLAG_FUNCTION) {
3130          metaState |= AMETA_FUNCTION_ON;
3131      }
3132
3133      policyFlags |= POLICY_FLAG_TRUSTED;
3134
3135      int32_t keyCode = args->keyCode;
3136      accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);
3137      //初始化KeyEvent
3138      KeyEvent event;
3139      event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
3140                       args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
3141                       args->downTime, args->eventTime);
3142
3143      android::base::Timer t; //mPolicy这里是指NativeInputManager 加入队列前执行拦截动作但并不改变流程
3144      mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
3145      if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
3146          ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
3147                std::to_string(t.duration().count()).c_str());
3148      }
3149
3150      bool needWake;
3151      { // acquire lock
3152          mLock.lock();
3153
3154          if (shouldSendKeyToInputFilterLocked(args)) {
3155              mLock.unlock();
3156
3157              policyFlags |= POLICY_FLAG_FILTERED;
3158              if (!mPolicy->filterInputEvent(&event, policyFlags)) {
3159                  return; // event was consumed by the filter
3160              }
3161
3162              mLock.lock();
3163          }
3164          //将NotifyKeyArgs*包装成KeyEntry*
3165          KeyEntry* newEntry =
3166                  new KeyEntry(args->id, args->eventTime, args->deviceId, args->source,
3167                               args->displayId, policyFlags, args->action, flags, keyCode,
3168                               args->scanCode, metaState, repeatCount, args->downTime);
3169          //将包装好的KeyEntry*加入到InputDispatcher的messageQueue中
3170          needWake = enqueueInboundEventLocked(newEntry);
3171          mLock.unlock();
3172      } // release lock
3173
3174      if (needWake) {//唤醒inputDispatcher的looper开始分发事件
3175          mLooper->wake();
3176      }
3177  }

InputDispatcher的notifyKey主要做了以下三件事:

  1. 调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程,调用链:

    • IMS.interceptKeyBeforeQueueing
    • mWindowManagerCallbacks.interceptKeyBeforeQueueing
    • mService.mPolicy.interceptKeyBeforeQueueing (mPolicy为WindowManagerPolicy)
    • PhoneWindowManager.interceptKeyBeforeQueueing (实现WindowManagerPolicy的接口)
  2. 当mInputFilterEnabled=true(该值默认为false,可通过setInputFilterEnabled设置),则调用NativeInputManager.filterInputEvent过滤输入事件;
    • 当返回值为false则过滤该事件,无机会交给InputDispatcher来分发
  3. 生成KeyEvent,并调用enqueueInboundEventLocked,将该事件加入到InputDispatcherd的成员变量mInboundQueue。

2.3.1 将输入事件加入分发队列

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
774  bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
775      bool needWake = mInboundQueue.empty();
776      mInboundQueue.push_back(entry); //将事件放到mInboundQueue的尾部
777      traceInboundQueueLengthLocked();
778
779      switch (entry->type) {
780          case EventEntry::Type::KEY: {
781              // Optimize app switch latency.
782              // If the application takes too long to catch up then we drop all events preceding
783              // the app switch key.
784              const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*entry);
785              if (isAppSwitchKeyEvent(keyEntry)) {
786                  if (keyEntry.action == AKEY_EVENT_ACTION_DOWN) {
787                      mAppSwitchSawKeyDown = true; //按下事件
788                  } else if (keyEntry.action == AKEY_EVENT_ACTION_UP) {
789                      if (mAppSwitchSawKeyDown) {
790  #if DEBUG_APP_SWITCH
791                          ALOGD("App switch is pending!");
792  #endif
793                          mAppSwitchDueTime = keyEntry.eventTime + APP_SWITCH_TIMEOUT;
794                          mAppSwitchSawKeyDown = false;
795                          needWake = true;
796                      }
797                  }
798              }
799              break;
800          }802          case EventEntry::Type::MOTION: {//当前App无响应且用户希望切换到其他应用窗口,则drop这个窗口之前所有的事件
803              if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(*entry))) {
804                  mNextUnblockedEvent = entry;
805                  needWake = true;
806              }
807              break;
808          }
809          case EventEntry::Type::FOCUS: {
810              LOG_ALWAYS_FATAL("Focus events should be inserted using enqueueFocusEventLocked");
811              break;
812          }
813          case EventEntry::Type::CONFIGURATION_CHANGED:
814          case EventEntry::Type::DEVICE_RESET: {
815              // nothing to do
816              break;
817          }
818      }
819
820      return needWake;
821  }955  static bool isAppSwitchKeyCode(int32_t keyCode) {
956      return keyCode == AKEYCODE_HOME || keyCode == AKEYCODE_ENDCALL ||
957              keyCode == AKEYCODE_APP_SWITCH;
958  }
959
960  bool InputDispatcher::isAppSwitchKeyEvent(const KeyEntry& keyEntry) {
961      return !(keyEntry.flags & AKEY_EVENT_FLAG_CANCELED) && isAppSwitchKeyCode(keyEntry.keyCode) &&
962              (keyEntry.policyFlags & POLICY_FLAG_TRUSTED) &&
963              (keyEntry.policyFlags & POLICY_FLAG_PASS_TO_USER);
964  }
//如果事件是手指移动的事件并且在这事件来之前的所有事件需要删除那么返回true
718  bool InputDispatcher::shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) {
719      const bool isPointerDownEvent = motionEntry.action == AMOTION_EVENT_ACTION_DOWN &&
720              (motionEntry.source & AINPUT_SOURCE_CLASS_POINTER);
721       //优化当前应用程序无响应,用户决定触摸另一个应用程序中的窗口的情况。 如果应用程序需要很长时间才能赶上进度,那么我们就会将触摸之前的所有事件放到另          //一个窗口中。
722      // Optimize case where the current application is unresponsive and the user
723      // decides to touch a window in a different application.
724      // If the application takes too long to catch up then we drop all events preceding
725      // the touch into the other window.
726      if (isPointerDownEvent && mAwaitedFocusedApplication != nullptr) {
727          int32_t displayId = motionEntry.displayId;
728          int32_t x = static_cast<int32_t>(
729                  motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
730          int32_t y = static_cast<int32_t>(
731                  motionEntry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
732          sp<InputWindowHandle> touchedWindowHandle =
733                  findTouchedWindowAtLocked(displayId, x, y, nullptr);
734          if (touchedWindowHandle != nullptr &&
735              touchedWindowHandle->getApplicationToken() !=
736                      mAwaitedFocusedApplication->getApplicationToken()) {
737              // User touched a different application than the one we are waiting on.
738              ALOGI("Pruning input queue because user touched a different application while waiting "
739                    "for %s",
740                    mAwaitedFocusedApplication->getName().c_str());
741              return true;
742          }
743          //或者,也许有一个手势监视器可以处理这个事件
744          // Alternatively, maybe there's a gesture monitor that could handle this event
745          std::vector<TouchedMonitor> gestureMonitors =
746                  findTouchedGestureMonitorsLocked(displayId, {});
747          for (TouchedMonitor& gestureMonitor : gestureMonitors) {
748              sp<Connection> connection =
749                      getConnectionLocked(gestureMonitor.monitor.inputChannel->getConnectionToken());
750              if (connection != nullptr && connection->responsive) {
751                  // This monitor could take more input. Drop all events preceding this
752                  // event, so that gesture monitor could get a chance to receive the stream
753                  ALOGW("Pruning the input queue because %s is unresponsive, but we have a "
754                        "responsive gesture monitor that may handle the event",
755                        mAwaitedFocusedApplication->getName().c_str());
756                  return true;
757              }
758          }
759      }
760      //为了防止卡住,如果我们有一个将要处理的KeyEvent,并且也有一些还没有处理的motion events,那么InputDispatcher会先等待motion events处理完//再来处理KeyEvent.这是因为motion events可能会切换到另一个用户想要获取到焦点的window,为了防止一直等待这种事件,我们会将keyEvent分发给当前        //获取焦点的窗口
761      // Prevent getting stuck: if we have a pending key event, and some motion events that have not
762      // yet been processed by some connections, the dispatcher will wait for these motion
763      // events to be processed before dispatching the key event. This is because these motion events
764      // may cause a new window to be launched, which the user might expect to receive focus.
765      // To prevent waiting forever for such events, just send the key to the currently focused window
766      if (isPointerDownEvent && mKeyIsWaitingForEventsTimeout) {
767          ALOGD("Received a new pointer down event, stop waiting for events to process and "
768                "just send the pending key event to the focused window.");
769          mKeyIsWaitingForEventsTimeout = now();
770      }
771      return false;
772  }832  sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId, int32_t x,
833                                                                   int32_t y, TouchState* touchState,
834                                                                   bool addOutsideTargets,
835                                                                   bool addPortalWindows) {
836      if ((addPortalWindows || addOutsideTargets) && touchState == nullptr) {
837          LOG_ALWAYS_FATAL(
838                  "Must provide a valid touch state if adding portal windows or outside targets");
839      }//通过遍历从前台到后台所有的windows来寻找触摸的window
840      // Traverse windows from front to back to find touched window.
841      const std::vector<sp<InputWindowHandle>> windowHandles = getWindowHandlesLocked(displayId);
842      for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
843          const InputWindowInfo* windowInfo = windowHandle->getInfo();//通过displayId来确认是否是触摸的window
844          if (windowInfo->displayId == displayId) {
845              int32_t flags = windowInfo->layoutParamsFlags;
846
847              if (windowInfo->visible) {
848                  if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
849                      bool isTouchModal = (flags &
850                                           (InputWindowInfo::FLAG_NOT_FOCUSABLE |
851                                            InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
852                      if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
853                          int32_t portalToDisplayId = windowInfo->portalToDisplayId;
854                          if (portalToDisplayId != ADISPLAY_ID_NONE &&
855                              portalToDisplayId != displayId) {
856                              if (addPortalWindows) {
857                                  // For the monitoring channels of the display.
858                                  touchState->addPortalWindow(windowHandle);
859                              }
860                              return findTouchedWindowAtLocked(portalToDisplayId, x, y, touchState,
861                                                               addOutsideTargets, addPortalWindows);
862                          }
863                          // Found window.
864                          return windowHandle;//找到目标窗口
865                      }
866                  }
867
868                  if (addOutsideTargets && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
869                      touchState->addOrUpdateWindow(windowHandle,
870                                                    InputTarget::FLAG_DISPATCH_AS_OUTSIDE,
871                                                    BitSet32(0));
872                  }
873              }
874          }
875      }
876      return nullptr;
877  }

2.3.2 唤醒Looper分发事件

唤醒Looper分发事件的条件主要有以下三种:

  1. 执行enqueueInboundEventLocked方法前,mInboundQueue队列为空,执行完必然不再为空,则需要唤醒分发线程;
  2. 当事件类型为key事件,且发生一对按下和抬起操作,则需要唤醒;
  3. 当事件类型为motion事件,且当前可触摸的窗口属于另一个应用,则需要唤醒.

唤醒的条件是根据enqueueInboundEventLocked的返回值来决定的:

3174      if (needWake) {//唤醒inputDispatcher的looper开始分发事件
3175          mLooper->wake();
3176      }
  • 节点/dev/input的event事件所对应的输入设备信息位于/proc/bus/input/devices,也可以通过getevent来获取事件. 不同的input事件所对应的物理input节点,比如常见的情形:

    • 屏幕触摸和(MENU,HOME,BACK)3按键:对应同一个input设备节点;
    • POWER和音量(下)键:对应同一个input设备节点;
    • 音量(上)键:对应同一个input设备节点;

3. InputDispacther线程

由1.2.2节可以知道InputDispacther线程执行的是threadLoop函数是在线程新建时传入的,传入的是dispatchOnce,所以InputDispacther线程的入口是dispatchOnce。

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
450  void InputDispatcher::dispatchOnce() {
451      nsecs_t nextWakeupTime = LONG_LONG_MAX;
452      { // acquire lock
453          std::scoped_lock _l(mLock);//通知所有关注的对象InputDispacther线程进入唤醒状态
454          mDispatcherIsAlive.notify_all();
455          //如果当前没有需要执行的command那么就执   行一次分发的流程,在分发的流程中可能会加入之后需要执行的command
456          // Run a dispatch loop if there are no pending commands.
457          // The dispatch loop might enqueue commands to run afterwards.
458          if (!haveCommandsLocked()) {
459              dispatchOnceInnerLocked(&nextWakeupTime);
460          }
461          //执行所有需要执行的command 如果有任意的command执行了,那么就立刻唤醒线程做下一次的轮询
462          // Run all pending commands if there are any.
463          // If any commands were run then force the next poll to wake up immediately.
464          if (runCommandsLockedInterruptible()) {
465              nextWakeupTime = LONG_LONG_MIN;
466          }
467          //如果我们仍然在等待一些事件,那么我们不得不提早唤醒去检查是否是一个app发生了ANR
468          // If we are still waiting for ack on some events,
469          // we might have to wake up earlier to check if an app is anr'ing.
470          const nsecs_t nextAnrCheck = processAnrsLocked();
471          nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
472           //如果我们没有command和event来执行和分发,那么我们需要通知所有的对象我们将要进入空闲状态
473          // We are about to enter an infinitely long sleep, because we have no commands or
474          // pending or queued events
475          if (nextWakeupTime == LONG_LONG_MAX) {
476              mDispatcherEnteredIdle.notify_all();
477          }
478      } // release lock
479       //线程进入epoll_wait等待状态
480      // Wait for callback or timeout or wake.  (make sure we round up, not down)
481      nsecs_t currentTime = now();
482      int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
483      mLooper->pollOnce(timeoutMillis);
484  }
982  bool InputDispatcher::haveCommandsLocked() const {
983      return !mCommandQueue.empty();
984  }

从上面的dispatchOnce可以知道InputDispacther主要做了以下三件事:

  1. 调用dispatchOnceInnerLocked执行分发流程期间可能会加入需要执行的command

  2. 如果有command需要执行那么调用runCommandsLockedInterruptible来执行command

  3. 调用processAnrsLocked来检查是否发生ANR

  4. 线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:

    (1)callback:通过回调方法来唤醒;

    (2)timeout:到达nextWakeupTime时间,超时唤醒;

    (3)wake: 主动调用Looper的wake()方法;

3.1 事件的分发

事件的分发调用的是dispatchOnceInnerLocked来实现的

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
563  void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
564      nsecs_t currentTime = now();
565      //无论何时当设备处于非交互状态导致正常的调度暂停时需要重置按键的重复定时器,这是为了确保当设备刚刚唤醒时,我们要中止按键重复
566      // Reset the key repeat timer whenever normal dispatch is suspended while the
567      // device is in a non-interactive state.  This is to ensure that we abort a key
568      // repeat if the device is just coming out of sleep.
569      if (!mDispatchEnabled) { //默认值为false
570          resetKeyRepeatLocked(); //重置操作
571      }
572      //如果分发被冻结,不要处理任何超时和传递新的事件
573      // If dispatching is frozen, do not process timeouts or try to deliver any new events.
574      if (mDispatchFrozen) {
575          if (DEBUG_FOCUS) {
576              ALOGD("Dispatch frozen.  Waiting some more.");
577          }
578          return;
579      }
580      //优化应用切换的延迟 本质上,当应用程序切换键(HOME/ENDCALL)被按下时,我们开始一个短暂的超时。当它过期时,我们抢占调度并删除所有其他挂起事件。
581      // Optimize latency of app switches.
582      // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
583      // been pressed.  When it expires, we preempt dispatch and drop all other pending events.
584      bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
585      if (mAppSwitchDueTime < *nextWakeupTime) {
586          *nextWakeupTime = mAppSwitchDueTime;
587      }
588
589      // Ready to start a new event.
590      // If we don't already have a pending event, go grab one.
591      if (!mPendingEvent) {
592          if (mInboundQueue.empty()) {
593              if (isAppSwitchDue) {//因为 inbound queue是空的,所以app switch 的keyEvent不会到来了,所以不需要再等待了
594                  // The inbound queue is empty so the app switch key we were waiting
595                  // for will never arrive.  Stop waiting for it.
596                  resetPendingAppSwitchLocked(false);
597                  isAppSwitchDue = false;
598              }
599              //如果合适,合成一个按键重复
600              // Synthesize a key repeat if appropriate.
601              if (mKeyRepeatState.lastKeyEntry) {
602                  if (currentTime >= mKeyRepeatState.nextRepeatTime) {
603                      mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
604                  } else {
605                      if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
606                          *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
607                      }
608                  }
609              }
610              //没有需要处理的事件,直接返回
611              // Nothing to do if there is no pending event.
612              if (!mPendingEvent) {
613                  return;
614              }
615          } else {//取出mInboundQueue的头部的事件
616              // Inbound queue has at least one entry.
617              mPendingEvent = mInboundQueue.front();
618              mInboundQueue.pop_front();
619              traceInboundQueueLengthLocked();
620          }
621          //把事件派发给应用程序
622          // Poke user activity for this event.
623          if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
624              pokeUserActivityLocked(*mPendingEvent);
625          }
626      }
627
628      // Now we have an event to dispatch.
629      // All events are eventually dequeued and processed this way, even if we intend to drop them.
630      ALOG_ASSERT(mPendingEvent != nullptr);
631      bool done = false;
632      DropReason dropReason = DropReason::NOT_DROPPED;
633      if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
634          dropReason = DropReason::POLICY;
635      } else if (!mDispatchEnabled) {
636          dropReason = DropReason::DISABLED;
637      }
638
639      if (mNextUnblockedEvent == mPendingEvent) {
640          mNextUnblockedEvent = nullptr;
641      }
642      //进入分发流程的分支,可以看到总共有5个分支其中configuration changes和device resets以及focus events不会被丢弃
643      switch (mPendingEvent->type) {
644          case EventEntry::Type::CONFIGURATION_CHANGED: {...
649              break;
650          }
651
652          case EventEntry::Type::DEVICE_RESET: {
653              ...
656              break;
657          }
658
659          case EventEntry::Type::FOCUS: {
660              ...
664              break;
665          }
666
667          case EventEntry::Type::KEY: {
668              KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
669              if (isAppSwitchDue) {
670                  if (isAppSwitchKeyEvent(*typedEntry)) {
671                      resetPendingAppSwitchLocked(true);
672                      isAppSwitchDue = false;
673                  } else if (dropReason == DropReason::NOT_DROPPED) {
674                      dropReason = DropReason::APP_SWITCH;
675                  }
676              }
677              if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *typedEntry)) {
678                  dropReason = DropReason::STALE;
679              }
680              if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
681                  dropReason = DropReason::BLOCKED;
682              }
683              done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
684              break;
685          }
686
687          case EventEntry::Type::MOTION: {...
699              break;
700          }
701      }
702
703      if (done) {
704          if (dropReason != DropReason::NOT_DROPPED) {
705              dropInboundEventLocked(*mPendingEvent, dropReason);
706          }
707          mLastDropReason = dropReason;
708
709          releasePendingEventLocked();
710          *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
711      }
712  }

dispatchOnceInnerLocked主要的工作:

  1. 根据mDispatchFrozen决定是否要冻结事件分发工作并不在分发事件
  2. 判断应用切换的事件是否超时
  3. mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量
  4. 根据事件的类型调用不同的分发函数,比如按键事件是dispatchKeyLocked
  5. 根据分发的返回值和dropReason来决定是否丢弃事件(dropInboundEventLocked)和释放事件(releasePendingEventLocked)

3.2 Key事件的分发

按键事件的分发是调用dispatchKeyLocked来实现的。

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
1141  bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
1142                                          DropReason* dropReason, nsecs_t* nextWakeupTime) {
1143      // Preprocessing.分发前的准备工作...
1178
1179      // Handle case where the policy asked us to try again later last time.
1180      if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
1181          //如果当前事件小于唤醒的时间进入等待状态if (currentTime < entry->interceptKeyWakeupTime) {
1182              if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
1183                  *nextWakeupTime = entry->interceptKeyWakeupTime;
1184              }
1185              return false; // wait until next wakeup
1186          }
1187          entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
1188          entry->interceptKeyWakeupTime = 0;
1189      }
1190
1191      // Give the policy a chance to intercept the key.
1192      if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
1193         //让policy有机会执行拦截操作构造一个doInterceptKeyBeforeDispatchingLockedInterruptible的command来执行来拦截if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
1194              std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
1195                      &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
1196              sp<InputWindowHandle> focusedWindowHandle =
1197                      getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(*entry));
1198              if (focusedWindowHandle != nullptr) {
1199                  commandEntry->inputChannel = getInputChannelLocked(focusedWindowHandle->getToken());
1200              }
1201              commandEntry->keyEntry = entry;
1202              postCommandLocked(std::move(commandEntry));
1203              entry->refCount += 1;
1204              return false; // wait for the command to run 等待command执行完毕
1205          } else {
1206              entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
1207          }
1208      } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
1209          if (*dropReason == DropReason::NOT_DROPPED) {
1210              *dropReason = DropReason::POLICY;
1211          }
1212      }
1213       //如果需要丢弃这个事件那么执行清理的动作
1214      // Clean up if dropping the event.
1215      if (*dropReason != DropReason::NOT_DROPPED) {
1216          setInjectionResult(entry,
1217                             *dropReason == DropReason::POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
1218                                                               : INPUT_EVENT_INJECTION_FAILED);
1219          mReporter->reportDroppedKey(entry->id);
1220          return true;
1221      }
1222       //验证目标,寻找焦点
1223      // Identify targets.
1224      std::vector<InputTarget> inputTargets;
1225      int32_t injectionResult =
1226              findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
1227      if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
1228          return false;
1229      }
1230
1231      setInjectionResult(entry, injectionResult);
1232      if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
1233          return true;
1234      }
1235
1236      // Add monitor channels from event's or focused display.
1237      addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
1238
1239      // Dispatch the key.
1240      dispatchEventLocked(currentTime, entry, inputTargets);
1241      return true;
1242  }

在以下场景下,有可能无法分发事件:

  1. 当前时间小于唤醒时间(nextWakeupTime)的情况;
  2. policy需要提前拦截事件的情况;
  3. 需要drop事件的情况;
  4. 寻找聚焦窗口失败的情况

如果成功跳过以上所有情况,则会进入执行事件分发的过程。

3.2.1 寻找焦点窗口

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
1477  int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
1478                                                          const EventEntry& entry,
1479                                                          std::vector<InputTarget>& inputTargets,
1480                                                          nsecs_t* nextWakeupTime) {
1481      std::string reason;
1482
1483      int32_t displayId = getTargetDisplayId(entry);
1484      sp<InputWindowHandle> focusedWindowHandle =
1485              getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
1486      sp<InputApplicationHandle> focusedApplicationHandle =
1487              getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);
1488      //如果没有焦点窗口和焦点应用那么就丢弃这个事件
1489      // If there is no currently focused window and no focused application
1490      // then drop the event.
1491      if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
1492          ALOGI("Dropping %s event because there is no focused window or focused application in "
1493                "display %" PRId32 ".",
1494                EventEntry::typeToString(entry.type), displayId);
1495          return INPUT_EVENT_INJECTION_FAILED; //input事件注入失败?
1496      }
1497       //兼容性行为,如果有焦点应用但是没有焦点窗口那么出发ANR.只有当我们有一个焦点事件要分派时才开始计数。 如果我们开始与另一个           //应用程序交互,ANR将被取消。 如果将“无焦点窗口ANR”移到策略中,则可以删除此代码。 Input不知道应用程序是否应该有一个聚焦窗口。
1498      // Compatibility behavior: raise ANR if there is a focused application, but no focused window.
1499      // Only start counting when we have a focused event to dispatch. The ANR is canceled if we
1500      // start interacting with another application via touch (app switch). This code can be removed
1501      // if the "no focused window ANR" is moved to the policy. Input doesn't know whether
1502      // an app is expected to have a focused window.
1503      if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
1504          if (!mNoFocusedWindowTimeoutTime.has_value()) {//我们只是发现没有焦点窗口但是没有超时时间时 开始ANR的计时
1505              // We just discovered that there's no focused window. Start the ANR timer
1506              const nsecs_t timeout = focusedApplicationHandle->getDispatchingTimeout(
1507                      DEFAULT_INPUT_DISPATCHING_TIMEOUT.count());
1508              mNoFocusedWindowTimeoutTime = currentTime + timeout;
1509              mAwaitedFocusedApplication = focusedApplicationHandle;
1510              mAwaitedApplicationDisplayId = displayId;
1511              ALOGW("Waiting because no window has focus but %s may eventually add a "
1512                    "window when it finishes starting up. Will wait for %" PRId64 "ms",
1513                    mAwaitedFocusedApplication->getName().c_str(), ns2ms(timeout));
1514              *nextWakeupTime = *mNoFocusedWindowTimeoutTime;
1515              return INPUT_EVENT_INJECTION_PENDING;
1516          } else if (currentTime > *mNoFocusedWindowTimeoutTime) {
1517              // Already raised ANR. Drop the event 已经出发ANR了,丢弃事件
1518              ALOGE("Dropping %s event because there is no focused window",
1519                    EventEntry::typeToString(entry.type));
1520              return INPUT_EVENT_INJECTION_FAILED;
1521          } else {
1522              // Still waiting for the focused window 仍然等待着焦点窗口
1523              return INPUT_EVENT_INJECTION_PENDING;
1524          }
1525      }
1526       //有一个不为空的无效的焦点窗口
1527      // we have a valid, non-null focused window
1528      resetNoFocusedWindowTimeoutLocked();
1529      //权限检查
1530      // Check permissions.
1531      if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
1532          return INPUT_EVENT_INJECTION_PERMISSION_DENIED;
1533      }
1534      //焦点窗口处于pause的状态
1535      if (focusedWindowHandle->getInfo()->paused) {
1536          ALOGI("Waiting because %s is paused", focusedWindowHandle->getName().c_str());
1537          return INPUT_EVENT_INJECTION_PENDING;
1538      }
1539      //如果事件时一个按键事件,我们必须等到之前所有的事件都处理完后在分发,这是因为之前的事件可能会改变焦点窗口,我们要确保接下来的按键都会分发到新的焦           //点窗口
1540      // If the event is a key event, then we must wait for all previous events to
1541      // complete before delivering it because previous events may have the
1542      // side-effect of transferring focus to a different window and we want to
1543      // ensure that the following keys are sent to the new window.
1544      //
1545      // Suppose the user touches a button in a window then immediately presses "A".
1546      // If the button causes a pop-up window to appear then we want to ensure that
1547      // the "A" key is delivered to the new pop-up window.  This is because users
1548      // often anticipate pending UI changes when typing on a keyboard.
1549      // To obtain this behavior, we must serialize key events with respect to all
1550      // prior input events.
1551      if (entry.type == EventEntry::Type::KEY) {
1552          if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle->getName().c_str())) {
1553              *nextWakeupTime = *mKeyIsWaitingForEventsTimeout;
1554              return INPUT_EVENT_INJECTION_PENDING;
1555          }
1556      }
1557      //将焦点窗口加入目标中
1558      // Success!  Output targets.
1559      addWindowTargetLocked(focusedWindowHandle,
1560                            InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
1561                            BitSet32(0), inputTargets);
1562
1563      // Done.
1564      return INPUT_EVENT_INJECTION_SUCCEEDED;
1565  }

在处理按键事件时需要等待之前所有的事件全部处理完成才能分发这个事件,这时因为之前的事件可能会转移焦点到新的窗口中,我们需要确保接下来的事件都分发到新的焦点窗口中。设想用户按下了一个按钮后立即按下了A键,如果按钮会弹出一个popWindow,那么我们想要确保A键被分发到新的弹出的window。 这是因为用户可能会预期等待UI的变化,在按下键盘的按键时。为了覆盖这中情形,我们必须将按键事件与所有之前前的输入事件序列化。

3.2.2 将焦点窗口加入事件目标中

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
2030  void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
2031                                              int32_t targetFlags, BitSet32 pointerIds,
2032                                              std::vector<InputTarget>& inputTargets) {
2033      std::vector<InputTarget>::iterator it =
2034              std::find_if(inputTargets.begin(), inputTargets.end(),
2035                           [&windowHandle](const InputTarget& inputTarget) {
2036                               return inputTarget.inputChannel->getConnectionToken() ==
2037                                       windowHandle->getToken();
2038                           });
2039
2040      const InputWindowInfo* windowInfo = windowHandle->getInfo();
2041      //如果不存在inputTargets中那么需要新建inputTarget放入inputTargets中
2042      if (it == inputTargets.end()) {
2043          InputTarget inputTarget;
2044          sp<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());//如果丢失了窗口的输入通道,那么就直接返回
2045          if (inputChannel == nullptr) {
2046              ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str());
2047              return;
2048          }
2049          inputTarget.inputChannel = inputChannel;
2050          inputTarget.flags = targetFlags;
2051          inputTarget.globalScaleFactor = windowInfo->globalScaleFactor;
2052          inputTargets.push_back(inputTarget);
2053          it = inputTargets.end() - 1;
2054      }
2055
2056      ALOG_ASSERT(it->flags == targetFlags);
2057      ALOG_ASSERT(it->globalScaleFactor == windowInfo->globalScaleFactor);
2058
2059      it->addPointers(pointerIds, -windowInfo->frameLeft, -windowInfo->frameTop,
2060                      windowInfo->windowXScale, windowInfo->windowYScale);
2061  }

addWindowTargetLocked主要是将焦点窗口的信息包装成InputTarget存入inputTargets中之后传给dispatchEventLocked 做真正的分发动作

3.2.3 分发按键事件

回到3.2中执行最后的分发流程,调用的是dispatchEventLocked 传入当前的时间,inputEvent和InputTargets作为参数。

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
1368  void InputDispatcher::dispatchEventLocked(nsecs_t currentTime, EventEntry* eventEntry,
1369                                            const std::vector<InputTarget>& inputTargets) {
1370      ATRACE_CALL();
1371  #if DEBUG_DISPATCH_CYCLE
1372      ALOGD("dispatchEventToCurrentInputTargets");
1373  #endif
1374
1375      ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
1376      //最后调用到PowerManagerService的userActivityFromNative
1377      pokeUserActivityLocked(*eventEntry);
1378
1379      for (const InputTarget& inputTarget : inputTargets) {
1380          sp<Connection> connection =
1381                  getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
1382          if (connection != nullptr) {
1383              prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
1384          } else {
1385              if (DEBUG_FOCUS) {
1386                  ALOGD("Dropping event delivery to target with channel '%s' because it "
1387                        "is no longer registered with the input dispatcher.",
1388                        inputTarget.inputChannel->getName().c_str());
1389              }
1390          }
1391      }
1392  }

将按键事件分发给具体的window调用的是prepareDispatchCycleLocked

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
2240  void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
2241                                                   const sp<Connection>& connection,
2242                                                   EventEntry* eventEntry,
2243                                                   const InputTarget& inputTarget) {
2244      if (ATRACE_ENABLED()) {
2245          std::string message =
2246                  StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
2247                               connection->getInputChannelName().c_str(), eventEntry->id);
2248          ATRACE_NAME(message.c_str());
2249      }
2250  #if DEBUG_DISPATCH_CYCLE
2251      ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
2252            "globalScaleFactor=%f, pointerIds=0x%x %s",
2253            connection->getInputChannelName().c_str(), inputTarget.flags,
2254            inputTarget.globalScaleFactor, inputTarget.pointerIds.value,
2255            inputTarget.getPointerInfoString().c_str());
2256  #endif
2257       //如果连接状态不正常 那么就直接返回
2258      // Skip this event if the connection status is not normal.
2259      // We don't want to enqueue additional outbound events if the connection is broken.
2260      if (connection->status != Connection::STATUS_NORMAL) {
2261  #if DEBUG_DISPATCH_CYCLE
2262          ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
2263                connection->getInputChannelName().c_str(), connection->getStatusLabel());
2264  #endif
2265          return;
2266      }
2267
2268      // Split a motion event if needed.
2269      if (inputTarget.flags & InputTarget::FLAG_SPLIT) {
2270          LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION,
2271                              "Entry type %s should not have FLAG_SPLIT",
2272                              EventEntry::typeToString(eventEntry->type));
2273
2274          const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry);
2275          if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) {
2276              MotionEntry* splitMotionEntry =
2277                      splitMotionEvent(originalMotionEntry, inputTarget.pointerIds);
2278              if (!splitMotionEntry) {
2279                  return; // split event was dropped
2280              }
2281              if (DEBUG_FOCUS) {
2282                  ALOGD("channel '%s' ~ Split motion event.",
2283                        connection->getInputChannelName().c_str());
2284                  logOutboundMotionDetails("  ", *splitMotionEntry);
2285              }
2286              enqueueDispatchEntriesLocked(currentTime, connection, splitMotionEntry, inputTarget);
2287              splitMotionEntry->release();
2288              return;
2289          }
2290      }
2291
2292      // Not splitting.  Enqueue dispatch entries for the event as is.
2293      enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
2294  }

不管是否需要分割,最终都是调用的enqueueDispatchEntriesLocked函数,将事件放到相应windows的队列中

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
2296  void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
2297                                                     const sp<Connection>& connection,
2298                                                     EventEntry* eventEntry,
2299                                                     const InputTarget& inputTarget) {
2300      if (ATRACE_ENABLED()) {
2301          std::string message =
2302                  StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
2303                               connection->getInputChannelName().c_str(), eventEntry->id);
2304          ATRACE_NAME(message.c_str());
2305      }
2306
2307      bool wasEmpty = connection->outboundQueue.empty();
2308       //根据dispatchMode来分别执行DispatchEntry事件加入队列的操作。
2309      // Enqueue dispatch entries for the requested modes.
2310      enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2311                                 InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
2312      enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2313                                 InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
2314      enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2315                                 InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
2316      enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2317                                 InputTarget::FLAG_DISPATCH_AS_IS);
2318      enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2319                                 InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
2320      enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2321                                 InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
2322
2323      // If the outbound queue was previously empty, start the dispatch cycle going.
2324      if (wasEmpty && !connection->outboundQueue.empty()) {
2325          startDispatchCycleLocked(currentTime, connection);
2326      }
2327  }2329  void InputDispatcher::enqueueDispatchEntryLocked(const sp<Connection>& connection,
2330                                                   EventEntry* eventEntry,
2331                                                   const InputTarget& inputTarget,
2332                                                   int32_t dispatchMode) {
2333      if (ATRACE_ENABLED()) {
2334          std::string message = StringPrintf("enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
2335                                             connection->getInputChannelName().c_str(),
2336                                             dispatchModeToString(dispatchMode).c_str());
2337          ATRACE_NAME(message.c_str());
2338      }
2339      int32_t inputTargetFlags = inputTarget.flags;//分发模式不匹配,直接返回connection的outboundQueue的尾部
2340      if (!(inputTargetFlags & dispatchMode)) {
2341          return;
2342      }
2343      inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
2344
2345      // This is a new event.
2346      // Enqueue a new dispatch entry onto the outbound queue for this connection.
2347      std::unique_ptr<DispatchEntry> dispatchEntry =
2348              createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
2349       //将EventEntry包装成 DispatchEntry放入到
2350      // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
2351      // different EventEntry than what was passed in.
2352      EventEntry* newEntry = dispatchEntry->eventEntry;
2353      // Apply target flags and update the connection's input state.
2354      switch (newEntry->type) {
2355          case EventEntry::Type::KEY: {
2356              const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*newEntry);
2357              dispatchEntry->resolvedEventId = keyEntry.id;
2358              dispatchEntry->resolvedAction = keyEntry.action;
2359              dispatchEntry->resolvedFlags = keyEntry.flags;
2360
2361              if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
2362                                                   dispatchEntry->resolvedFlags)) {
2363  #if DEBUG_DISPATCH_CYCLE
2364                  ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
2365                        connection->getInputChannelName().c_str());
2366  #endif
2367                  return; // skip the inconsistent event
2368              }
2369              break;
2370          }...
2447      }
2448
2449      // Remember that we are waiting for this dispatch to complete.
2450      if (dispatchEntry->hasForegroundTarget()) {
2451          incrementPendingForegroundDispatches(newEntry);
2452      }
2453
2454      // Enqueue the dispatch entry.
2455      connection->outboundQueue.push_back(dispatchEntry.release());
2456      traceOutboundQueueLength(connection);
2457  }

上面的流程总结一下就是将InputDispatcher中mInboundQueue中的事件取出后, 找到目标window后,封装dispatchEntry加入到connection的outbound队列.

如果connection的outbound在执行完enqueueDispatchEntryLocked后不为空了,那么需要执行startDispatchCycleLocked来进行分发.

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
2487  void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
2488                                                 const sp<Connection>& connection) {...//check链接正常的同时循环取出outboundQueue的dispatchEntry对象
2498      while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.empty()) {
2499          DispatchEntry* dispatchEntry = connection->outboundQueue.front();
2500          dispatchEntry->deliveryTime = currentTime;
2501          const nsecs_t timeout =
2502                  getDispatchingTimeoutLocked(connection->inputChannel->getConnectionToken());
2503          dispatchEntry->timeoutTime = currentTime + timeout;
2504           //分发事件
2505          // Publish the event.
2506          status_t status;
2507          EventEntry* eventEntry = dispatchEntry->eventEntry;
2508          switch (eventEntry->type) {
2509              case EventEntry::Type::KEY: {
2510                  const KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
2511                  std::array<uint8_t, 32> hmac = getSignature(*keyEntry, *dispatchEntry);
2512                  //分发按键事件
2513                  // Publish the key event.
2514                  status =
2515                          connection->inputPublisher
2516                                  .publishKeyEvent(dispatchEntry->seq, dispatchEntry->resolvedEventId,
2517                                                   keyEntry->deviceId, keyEntry->source,
2518                                                   keyEntry->displayId, std::move(hmac),
2519                                                   dispatchEntry->resolvedAction,
2520                                                   dispatchEntry->resolvedFlags, keyEntry->keyCode,
2521                                                   keyEntry->scanCode, keyEntry->metaState,
2522                                                   keyEntry->repeatCount, keyEntry->downTime,
2523                                                   keyEntry->eventTime);
2524                  break;
2525              }//其他类型的事件....
2603          }
2604
2605          // Check the result.
2606          if (status) {//分发失败的情况
2607              if (status == WOULD_BLOCK) {
2608                  if (connection->waitQueue.empty()) {
2609                      ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
2610                            "This is unexpected because the wait queue is empty, so the pipe "
2611                            "should be empty and we shouldn't have any problems writing an "
2612                            "event to it, status=%d",
2613                            connection->getInputChannelName().c_str(), status);
2614                      abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
2615                  } else {
2616                      // Pipe is full and we are waiting for the app to finish process some events
2617                      // before sending more events to it.
2618  #if DEBUG_DISPATCH_CYCLE
2619                      ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
2620                            "waiting for the application to catch up",
2621                            connection->getInputChannelName().c_str());
2622  #endif
2623                  }
2624              } else {
2625                  ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
2626                        "status=%d",
2627                        connection->getInputChannelName().c_str(), status);
2628                  abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
2629              }
2630              return;
2631          }
2632           //从outboundQueue中取出事件,重新放入waitQueue队列
2633          // Re-enqueue the event on the wait queue.
2634          connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
2635                                                      connection->outboundQueue.end(),
2636                                                      dispatchEntry));
2637          traceOutboundQueueLength(connection);
2638          connection->waitQueue.push_back(dispatchEntry);
2639          if (connection->responsive) {
2640              mAnrTracker.insert(dispatchEntry->timeoutTime,
2641                                 connection->inputChannel->getConnectionToken());
2642          }
2643          traceWaitQueueLength(connection);
2644      }
2645  }

startDispatchCycleLocked的主要功能: 从outboundQueue中取出事件,放入waitQueue队列

  • startDispatchCycleLocked触发时机:当起初connection.outboundQueue等于空, 经enqueueDispatchEntryLocked处理后, outboundQueue不等于空。
  • startDispatchCycleLocked主要功能: 从outboundQueue中取出事件,重新放入waitQueue队列
  • publishKeyEvent执行结果status不等于OK的情况下:
    • WOULD_BLOCK,且waitQueue等于空,则调用abortBrokenDispatchCycleLocked(),该方法最终会调用到Java层的IMS.notifyInputChannelBroken().
    • WOULD_BLOCK,且waitQueue不等于空,则处于阻塞状态,即inputPublisherBlocked=true
    • 其他情况,则调用abortBrokenDispatchCycleLocked
  • abortBrokenDispatchCycleLocked()方法最终会调用到Java层的IMS.notifyInputChannelBroken().

真正分发事件的工作是

/frameworks/native/libs/input/InputTransport.cpp
440  status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
441                                           int32_t source, int32_t displayId,
442                                           std::array<uint8_t, 32> hmac, int32_t action,
443                                           int32_t flags, int32_t keyCode, int32_t scanCode,
444                                           int32_t metaState, int32_t repeatCount, nsecs_t downTime,
445                                           nsecs_t eventTime) {
446      if (ATRACE_ENABLED()) {
447          std::string message = StringPrintf("publishKeyEvent(inputChannel=%s, keyCode=%" PRId32 ")",
448                  mChannel->getName().c_str(), keyCode);
449          ATRACE_NAME(message.c_str());
450      }
451      if (DEBUG_TRANSPORT_ACTIONS) {
452          ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, "
453                "action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
454                "downTime=%" PRId64 ", eventTime=%" PRId64,
455                mChannel->getName().c_str(), seq, deviceId, source, action, flags, keyCode, scanCode,
456                metaState, repeatCount, downTime, eventTime);
457      }
458
459      if (!seq) {
460          ALOGE("Attempted to publish a key event with sequence number 0.");
461          return BAD_VALUE;
462      }
463
464      InputMessage msg;
465      msg.header.type = InputMessage::Type::KEY;
466      msg.body.key.seq = seq;
467      msg.body.key.eventId = eventId;
468      msg.body.key.deviceId = deviceId;
469      msg.body.key.source = source;
470      msg.body.key.displayId = displayId;
471      msg.body.key.hmac = std::move(hmac);
472      msg.body.key.action = action;
473      msg.body.key.flags = flags;
474      msg.body.key.keyCode = keyCode;
475      msg.body.key.scanCode = scanCode;
476      msg.body.key.metaState = metaState;
477      msg.body.key.repeatCount = repeatCount;
478      msg.body.key.downTime = downTime;
479      msg.body.key.eventTime = eventTime;
480      return mChannel->sendMessage(&msg);
481  }

InputChannel通过socket向远端的socket发送消息。

接3.1最后会执行清理动作调用releasePendingEventLocked

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
1015  void InputDispatcher::releasePendingEventLocked() {
1016      if (mPendingEvent) {
1017          releaseInboundEventLocked(mPendingEvent);
1018          mPendingEvent = nullptr;
1019      }
1020  }
1021  //将mNextUnblockedEvent置为null并将EventEntry加入到mRecentQueue的队列中
1022  void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
1023      InjectionState* injectionState = entry->injectionState;//如果状态还是INPUT_EVENT_INJECTION_PENDING设置injectionResult为INPUT_EVENT_INJECTION_FAILED
1024      if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
1025  #if DEBUG_DISPATCH_CYCLE
1026          ALOGD("Injected inbound event was dropped.");
1027  #endif
1028          setInjectionResult(entry, INPUT_EVENT_INJECTION_FAILED);
1029      }
1030      if (entry == mNextUnblockedEvent) {
1031          mNextUnblockedEvent = nullptr;
1032      }
1033      addRecentEventLocked(entry);
1034      entry->release();
1035  }

3.3 command的执行

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
986  bool InputDispatcher::runCommandsLockedInterruptible() {
987      if (mCommandQueue.empty()) {
988          return false;
989      }
990     //遍历mCommandQueue 调用command去执行,之后清理
991      do {
992          std::unique_ptr<CommandEntry> commandEntry = std::move(mCommandQueue.front());
993          mCommandQueue.pop_front();
994          Command command = commandEntry->command;
995          command(*this, commandEntry.get()); // commands are implicitly 'LockedInterruptible'
996
997          commandEntry->connection.clear();
998      } while (!mCommandQueue.empty());
999      return true;
1000  }

可以看到是调用每一个commandEntry的command函数去执行,举个例子,在3.2中如果policy需要提前拦截事件,那么就会构造一个CommandEntry对象如下:

1191      // Give the policy a chance to intercept the key.
1192      if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
1193         //让policy有机会执行拦截操作构造一个doInterceptKeyBeforeDispatchingLockedInterruptible的command来执行来拦截if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
1194              std::unique_ptr<CommandEntry> commandEntry = std::make_unique<CommandEntry>(
1195                      &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
1196              sp<InputWindowHandle> focusedWindowHandle =
1197                      getValueByKey(mFocusedWindowHandlesByDisplay, getTargetDisplayId(*entry));
1198              if (focusedWindowHandle != nullptr) {
1199                  commandEntry->inputChannel = getInputChannelLocked(focusedWindowHandle->getToken());
1200              }
1201              commandEntry->keyEntry = entry;
1202              postCommandLocked(std::move(commandEntry));
1203              entry->refCount += 1;
1204              return false; // wait for the command to run 等待command执行完毕
1205          } else {
1206              entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
1207          }

可以看到传入的command是doInterceptKeyBeforeDispatchingLockedInterruptible最后回调到InputManagerService的interceptKeyBeforeDispatching,对于command的处理只要了解机制即可。

3.4 处理ANR

ANR的处理是在processAnrsLocked中进行的如下:

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
518  nsecs_t InputDispatcher::processAnrsLocked() {
519      const nsecs_t currentTime = now();
520      nsecs_t nextAnrCheck = LONG_LONG_MAX;
521      // Check if we are waiting for a focused window to appear. Raise ANR if waited too long
522      if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
523          if (currentTime >= *mNoFocusedWindowTimeoutTime) {//如果在一定时间内都没有focusWindows那么就调用processNoFocusedWindowAnrLocked出发ANR
524              processNoFocusedWindowAnrLocked();
525              mAwaitedFocusedApplication.clear();
526              mNoFocusedWindowTimeoutTime = std::nullopt;
527              return LONG_LONG_MIN;
528          } else {
529              // Keep waiting
530              const nsecs_t millisRemaining = ns2ms(*mNoFocusedWindowTimeoutTime - currentTime);
531              ALOGW("Still no focused window. Will drop the event in %" PRId64 "ms", millisRemaining);
532              nextAnrCheck = *mNoFocusedWindowTimeoutTime;
533          }
534      }
535
536      // Check if any connection ANRs are due
537      nextAnrCheck = std::min(nextAnrCheck, mAnrTracker.firstTimeout());
538      if (currentTime < nextAnrCheck) { // most likely scenario
539          return nextAnrCheck;          // everything is normal. Let's check again at nextAnrCheck
540      }
541      //如果有某个链接无法响应了也会触发ANR
542      // If we reached here, we have an unresponsive connection.
543      sp<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
544      if (connection == nullptr) {
545          ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
546          return nextAnrCheck;
547      }
548      connection->responsive = false;
549      // Stop waking up for this unresponsive connection
550      mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken());
551      onAnrLocked(*connection);
552      return LONG_LONG_MIN;
553  }

其中mNoFocusedWindowTimeoutTime的值是在3.2.1的寻找焦点窗口设置的。最终processNoFocusedWindowAnrLocked和onAnrLocked都会创建一个doNotifyAnrLockedInterruptible的Command添加到mCommandQueuez中等待执行。ANR计时的重置主要是调用resetNoFocusedWindowTimeoutLocked来重置mNoFocusedWindowTimeoutTime的值主要有以下函数会调用:setFocusedApplication、setInputDispatchMode、resetAndDropEverythingLocked

InputDispacther线程的主要工作如下:

  1. dispatchOnceInnerLocked(): 从InputDispatcher的mInboundQueue队列,取出事件EventEntry。另外该方法开始执行的时间点(currentTime)便是后续事件dispatchEntry的分发时间(deliveryTime)
  2. dispatchKeyLocked():满足一定条件时会添加命令doInterceptKeyBeforeDispatchingLockedInterruptible;
  3. enqueueDispatchEntryLocked():生成事件DispatchEntry并加入connection的outbound队列
  4. startDispatchCycleLocked():从outboundQueue中取出事件DispatchEntry, 根据类型调用publishKeyEvent分发事件给focusWindow并将Event放入connection的waitQueue队列;
  5. publishKeyEventz则调用InputChannel.sendMessage通过socket方式将消息发送给远程进程;
  6. runCommandsLockedInterruptible():通过循环遍历地方式,依次处理mCommandQueue队列中的所有命令。而mCommandQueue队列中的命令是通过postCommandLocked()方式向该队列添加的。

4.建立inputChannel通信

从3.2.3可以知道最后input事件是调用mChannel->sendMessage通过socket通讯将事件发送给焦点窗口那么接下来我们去看一下这个socket的对端是在哪儿建立的。socket的建立是在Activity的启动时建立的流程如下:可以看是在activity显示decorView时建立的

从上图来看主要的建立过程是调用的win.openInputChannel执行的所以我们从这里看起:

/frameworks/base/services/core/java/com/android/server/wm/WindowState.java
2466      void openInputChannel(InputChannel outInputChannel) {//outInputChannel是应用进程传递过来的引用
2467          if (mInputChannel != null) {2468              throw new IllegalStateException("Window already has an input channel.");
2469          }
2470          String name = getName();//创建一对socket
2471          InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2472          mInputChannel = inputChannels[0];
2473          mClientChannel = inputChannels[1];//将服务端注册给inputdispacther
2474          mWmService.mInputManager.registerInputChannel(mInputChannel);
2475          mInputWindowHandle.token = mInputChannel.getToken();
2476          if (outInputChannel != null) {//将客户端转移给应用进程传过来的outInputChannel
2477              mClientChannel.transferTo(outInputChannel);
2478              mClientChannel.dispose();
2479              mClientChannel = null;
2480          } else {2481              // If the window died visible, we setup a dummy input channel, so that taps
2482              // can still detected by input monitor channel, and we can relaunch the app.
2483              // Create dummy event receiver that simply reports all events as handled.
2484              mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
2485          }
2486          mWmService.mInputToWindowMap.put(mInputWindowHandle.token, this);
2487      }

4.1 创建input socket

/frameworks/base/core/java/android/view/InputChannel.java
93      public static InputChannel[] openInputChannelPair(String name) {94          if (name == null) {95              throw new IllegalArgumentException("name must not be null");
96          }
97
98          if (DEBUG) {99              Slog.d(TAG, "Opening input channel pair '" + name + "'");
100          }
101          return nativeOpenInputChannelPair(name);
102      }

通过JNI调用到native层

/frameworks/base/core/jni/android_view_InputChannel.cpp
127  static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
128          jclass clazz, jstring nameObj) {
129      ScopedUtfChars nameChars(env, nameObj);
130      std::string name = nameChars.c_str();
131
132      sp<InputChannel> serverChannel;
133      sp<InputChannel> clientChannel;//调用native层的InputChannel创建一对socket
134      status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
135
136      if (result) {
137          std::string message = android::base::StringPrintf(
138                  "Could not open input channel pair : %s", strerror(-result));
139          jniThrowRuntimeException(env, message.c_str());
140          return nullptr;
141      }
142      //将native的socket转成java层的返回
143      jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, nullptr);
144      if (env->ExceptionCheck()) {
145          return nullptr;
146      }
147      //类似于装箱将native的InputChanel转成java层的inputchannel
148      jobject serverChannelObj = android_view_InputChannel_createInputChannel(env, serverChannel);
149      if (env->ExceptionCheck()) {
150          return nullptr;
151      }
152
153      jobject clientChannelObj = android_view_InputChannel_createInputChannel(env, clientChannel);
154      if (env->ExceptionCheck()) {
155          return nullptr;
156      }
157
158      env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
159      env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
160      return channelPair;
161  }/frameworks/native/libs/input/InputTransport.cpp
275  status_t InputChannel::openInputChannelPair(const std::string& name,
276          sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
277      int sockets[2];
278      if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
279          status_t result = -errno;
280          ALOGE("channel '%s' ~ Could not create socket pair.  errno=%d",
281                  name.c_str(), errno);
282          outServerChannel.clear();
283          outClientChannel.clear();
284          return result;
285      }
286
287      int bufferSize = SOCKET_BUFFER_SIZE;
288      setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
289      setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
290      setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
291      setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
292
293      sp<IBinder> token = new BBinder();
294
295      std::string serverChannelName = name + " (server)";
296      android::base::unique_fd serverFd(sockets[0]);
297      outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);
298
299      std::string clientChannelName = name + " (client)";
300      android::base::unique_fd clientFd(sockets[1]);
301      outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);
302      return OK;
303  }

4.2 注册socket的服务端给InputManagerService

这一步是调用的mWmService.mInputManager.registerInputChannel执行的。

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
559      public void registerInputChannel(InputChannel inputChannel) {560          if (inputChannel == null) {561              throw new IllegalArgumentException("inputChannel must not be null.");
562          }
563
564          nativeRegisterInputChannel(mPtr, inputChannel);
565      }

同样也是JNI调用到native层

/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
1352  static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
1353          jlong ptr, jobject inputChannelObj) {
1354      NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
1355      //类似于拆箱将java层的InputChanel转成native层的inputchannel
1356      sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
1357              inputChannelObj);
1358      if (inputChannel == nullptr) {
1359          throwInputChannelNotInitialized(env);
1360          return;
1361      }
1362      //im指的是nativeInputManager 最终调用的是inputdispatch的registerInputChannel
1363      status_t status = im->registerInputChannel(env, inputChannel);
1364
1365      if (status) {
1366          std::string message;
1367          message += StringPrintf("Failed to register input channel.  status=%d", status);
1368          jniThrowRuntimeException(env, message.c_str());
1369          return;
1370      }
1371
1372      android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
1373              handleInputChannelDisposed, im);
1374  }
427  status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
428          const sp<InputChannel>& inputChannel) {
429      ATRACE_CALL();
430      return mInputManager->getDispatcher()->registerInputChannel(inputChannel);
431  }/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
4299  status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
4300  #if DEBUG_REGISTRATION
4301      ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str());
4302  #endif
4303
4304      { // acquire lock
4305          std::scoped_lock _l(mLock);
4306          sp<Connection> existingConnection = getConnectionLocked(inputChannel->getConnectionToken());
4307          if (existingConnection != nullptr) {
4308              ALOGW("Attempted to register already registered input channel '%s'",
4309                    inputChannel->getName().c_str());
4310              return BAD_VALUE;
4311          }
4312
4313          sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator);
4314
4315          int fd = inputChannel->getFd();
4316          mConnectionsByFd[fd] = connection;
4317          mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel;
4318
4319          mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
4320      } // release lock
4321
4322      // Wake the looper because some connections have changed.
4323      mLooper->wake();
4324      return OK;
4325  }

将socket加入到InputDispatch的looper的监控中,当socket有数据写入时,调用handleReceiveCallback来处理消息。

4.3 将socket的客户端给应用进程

调用 mClientChannel.transferTo(outInputChannel);将socket的客户端给了应用进程传过来的outInputChannel,接着应用进程拿到socket的客户端后创建了一个 WindowInputEventReceiver

/frameworks/base/core/java/android/view/ViewRootImpl.java
922      public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
923              int userId) {...
1124                  if (inputChannel != null) {1125                      if (mInputQueueCallback != null) {1126                          mInputQueue = new InputQueue();
1127                          mInputQueueCallback.onInputQueueCreated(mInputQueue);
1128                      }
1129                      mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
1130                              Looper.myLooper());
1131                  }...}
8183          public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {8184              super(inputChannel, looper);
8185          }/frameworks/base/core/java/android/view/InputEventReceiver.java64      public InputEventReceiver(InputChannel inputChannel, Looper looper) {65          if (inputChannel == null) {66              throw new IllegalArgumentException("inputChannel must not be null");
67          }
68          if (looper == null) {69              throw new IllegalArgumentException("looper must not be null");
70          }
71
72          mInputChannel = inputChannel;
73          mMessageQueue = looper.getQueue();
74          mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
75                  inputChannel, mMessageQueue);
76
77          mCloseGuard.open("dispose");
78      }

InputEventReceiver则是通过JNI调用到native层去初始化

/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
357  static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
358          jobject inputChannelObj, jobject messageQueueObj) {
359      sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
360              inputChannelObj);...
371
372      sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
373              receiverWeak, inputChannel, messageQueue);
374      status_t status = receiver->initialize();
375      if (status) {
376          String8 message;
377          message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
378          jniThrowRuntimeException(env, message.string());
379          return 0;
380      }
381
382      receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
383      return reinterpret_cast<jlong>(receiver.get());
384  }
111  status_t NativeInputEventReceiver::initialize() {
112      setFdEvents(ALOOPER_EVENT_INPUT);
113      return OK;
114  }
151  void NativeInputEventReceiver::setFdEvents(int events) {
152      if (mFdEvents != events) {
153          mFdEvents = events;
154          int fd = mInputConsumer.getChannel()->getFd();
155          if (events) {
156              mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);
157          } else {
158              mMessageQueue->getLooper()->removeFd(fd);
159          }
160      }
161  }

最终将socket加入到应用主线程的looper的监听中当有消息时就回调NativeInputEventReceiver.handleEvent来处理

至此客户端(应用主线程)和服务端(inputDispatcher)建立通信,inputDispatcher分发的输入事件即可被应用感知

InputChannel的通信为何不用Binder而要用Socket?

因为要实现异步通信的话,socket只需要两个线程参与(Pipe两端各一个)但是如果是Binder为了实现异步接收,发送端和接收端都各需要两个线程,Binder线程和处理线程(不能再binder线程中处理输入事件,会阻塞发送端的调用线程)所以比起socket会多出一倍的线程消耗,所以socket比起binder更高效。

5.应用端接受input事件

在3.2.3小节中我们知道InputDispatcher会通过Socket将事件发送给应用端,当socket有数据写入时,应用端会调用NativeInputEventReceiver的handleEvent来处理事件如下:

/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
163  int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {...
174
175      if (events & ALOOPER_EVENT_INPUT) {
176          JNIEnv* env = AndroidRuntime::getJNIEnv();//从socket中读取事件并消费
177          status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
178          mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
179          return status == OK || status == NO_MEMORY ? 1 : 0;
180      }
181  ...
221  }
223  status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
224          bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {...
236
237      ScopedLocalRef<jobject> receiverObj(env, nullptr);
238      bool skipCallbacks = false;
239      for (;;) {
240          uint32_t seq;
241          InputEvent* inputEvent;
242          //循环读取socket的数据并将其转换成InputEvent
243          status_t status = mInputConsumer.consume(&mInputEventFactory,
244                  consumeBatches, frameTime, &seq, &inputEvent);
245          if (status != OK && status != WOULD_BLOCK) {
246              ALOGE("channel '%s' ~ Failed to consume input event.  status=%d",
247                    getInputChannelName().c_str(), status);
248              return status;
249          }
250
251          if (status == WOULD_BLOCK) {
252              if (!skipCallbacks && !mBatchedInputEventPending && mInputConsumer.hasPendingBatch()) {
253                  // There is a pending batch.  Come back later.
254                  if (!receiverObj.get()) {
255                      receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
256                      if (!receiverObj.get()) {
257                          ALOGW("channel '%s' ~ Receiver object was finalized "
258                                "without being disposed.",
259                                getInputChannelName().c_str());
260                          return DEAD_OBJECT;
261                      }
262                  }
263
264                  mBatchedInputEventPending = true;
265                  if (kDebugDispatchCycle) {
266                      ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
267                            getInputChannelName().c_str());
268                  }
269
270                  env->CallVoidMethod(receiverObj.get(),
271                                      gInputEventReceiverClassInfo.onBatchedInputEventPending,
272                                      mInputConsumer.getPendingBatchSource());
273                  if (env->ExceptionCheck()) {
274                      ALOGE("Exception dispatching batched input events.");
275                      mBatchedInputEventPending = false; // try again later
276                  }
277              }
278              return OK;
279          }
280          assert(inputEvent);
281
282          if (!skipCallbacks) {
283              if (!receiverObj.get()) {
284                  receiverObj.reset(jniGetReferent(env, mReceiverWeakGlobal));
285                  if (!receiverObj.get()) {
286                      ALOGW("channel '%s' ~ Receiver object was finalized "
287                              "without being disposed.", getInputChannelName().c_str());
288                      return DEAD_OBJECT;
289                  }
290              }
291
292              jobject inputEventObj;
293              switch (inputEvent->getType()) {
294              case AINPUT_EVENT_TYPE_KEY:
295                  if (kDebugDispatchCycle) {
296                      ALOGD("channel '%s' ~ Received key event.", getInputChannelName().c_str());
297                  }//将native的inputEvent转换成java的inputEvent
298                  inputEventObj = android_view_KeyEvent_fromNative(env,
299                          static_cast<KeyEvent*>(inputEvent));
300                  break;
301                 //输入事件是其他类型的情况比如 motion focus....
330              }
331
332              if (inputEventObj) {
333                  if (kDebugDispatchCycle) {
334                      ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName().c_str());
335                  }//调用java层InputEventReceiver.java的dispatchInputEvent分发事件
336                  env->CallVoidMethod(receiverObj.get(),
337                          gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
338                  if (env->ExceptionCheck()) {
339                      ALOGE("Exception dispatching input event.");
340                      skipCallbacks = true;
341                  }
342                  env->DeleteLocalRef(inputEventObj);
343              } else {
344                  ALOGW("channel '%s' ~ Failed to obtain event object.",
345                          getInputChannelName().c_str());
346                  skipCallbacks = true;
347              }
348          }
349
350          if (skipCallbacks) {
351              mInputConsumer.sendFinishedSignal(seq, false);
352          }
353      }
354  }

5.1 应用层input事件的获取

/frameworks/native/libs/input/InputTransport.cpp
611  status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
612                                  nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
613      if (DEBUG_TRANSPORT_ACTIONS) {
614          ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
615                mChannel->getName().c_str(), toString(consumeBatches), frameTime);
616      }
617
618      *outSeq = 0;
619      *outEvent = nullptr;
620
621      // Fetch the next input message.
622      // Loop until an event can be returned or no additional events are received.
623      while (!*outEvent) {
624          if (mMsgDeferred) {
625              // mMsg contains a valid input message from the previous call to consume
626              // that has not yet been processed.
627              mMsgDeferred = false;
628          } else {
629              // Receive a fresh message.
630              status_t result = mChannel->receiveMessage(&mMsg);
631              if (result) {
632                  // Consume the next batched event unless batches are being held for later.
633                  ...
643                  return result;
644              }
645          }
646
647          switch (mMsg.header.type) {
648              case InputMessage::Type::KEY: {
649                  KeyEvent* keyEvent = factory->createKeyEvent();
650                  if (!keyEvent) return NO_MEMORY;
651                  //将socket里的数据转成KeyEvent
652                  initializeKeyEvent(keyEvent, &mMsg);
653                  *outSeq = mMsg.body.key.seq;
654                  *outEvent = keyEvent;
655                  if (DEBUG_TRANSPORT_ACTIONS) {
656                      ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
657                            mChannel->getName().c_str(), *outSeq);
658                  }
659              break;
660              }
661
662             ...
746      }
747      return OK;
748  }

上面就是应用进程从socket中读取input事件并转成native的inputEvent流程

5.2 应用层input事件的分发

/frameworks/base/core/java/android/view/InputEventReceiver.java
219      private void dispatchInputEvent(int seq, InputEvent event) {220          mSeqMap.put(event.getSequenceNumber(), seq);
221          onInputEvent(event);
222      }
/frameworks/base/core/java/android/view/ViewRootImpl.java$WindowInputEventReceiver
8188          public void onInputEvent(InputEvent event) {8189              Trace.traceBegin(Trace.TRACE_TAG_VIEW, "processInputEventForCompatibility");
8190              List<InputEvent> processedEvents;
8191              try {//如果应用的mTargetSdkVersion < 6.0并且输入事件是motionEvent才会返回一个list,否则返回null
8192                  processedEvents =
8193                      mInputCompatProcessor.processInputEventForCompatibility(event);
8194              } finally {8195                  Trace.traceEnd(Trace.TRACE_TAG_VIEW);
8196              }
8197              if (processedEvents != null) {8198                  if (processedEvents.isEmpty()) {8199                      // InputEvent consumed by mInputCompatProcessor
8200                      finishInputEvent(event, true);
8201                  } else {8202                      for (int i = 0; i < processedEvents.size(); i++) {8203                          enqueueInputEvent(
8204                                  processedEvents.get(i), this,
8205                                  QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY, true);
8206                      }
8207                  }
8208              } else {8209                  enqueueInputEvent(event, this, 0, true);
8210              }
8211          }7976      void enqueueInputEvent(InputEvent event,
7977              InputEventReceiver receiver, int flags, boolean processImmediately) {7978          QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
7979
7980          // Always enqueue the input event in order, regardless of its time stamp.
7981          // We do this because the application or the IME may inject key events
7982          // in response to touch events and we want to ensure that the injected keys
7983          // are processed in the order they were received and we cannot trust that
7984          // the time stamp of injected events are monotonic.
7985          QueuedInputEvent last = mPendingInputEventTail;
7986          if (last == null) {7987              mPendingInputEventHead = q;
7988              mPendingInputEventTail = q;
7989          } else {7990              last.mNext = q;
7991              mPendingInputEventTail = q;
7992          }
7993          mPendingInputEventCount += 1;
7994          Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
7995                  mPendingInputEventCount);
7996
7997          if (processImmediately) {//立即处理
7998              doProcessInputEvents();
7999          } else {//利用handle延时处理最终仍然是调用的doProcessInputEvents mProcessInputEventsScheduled被置成true
8000              scheduleProcessInputEvents();
8001          }
8002      }

java层分发事件最终调用的是enqueueInputEvent,将InputEvent转成QueuedInputEvent并插入到一个单链表中,接着如果需要马上处理就调用doProcessInputEvents否则就调用scheduleProcessInputEvents。从之前传过来的参数可以知道KeyEvent是调用doProcessInputEvents马上处理。

/frameworks/base/core/java/android/view/ViewRootImpl.java
8013      void doProcessInputEvents() {8014          // Deliver all pending input events in the queue.
8015          while (mPendingInputEventHead != null) {8016              QueuedInputEvent q = mPendingInputEventHead;
8017              mPendingInputEventHead = q.mNext;
8018              if (mPendingInputEventHead == null) {8019                  mPendingInputEventTail = null;
8020              }
8021              q.mNext = null;
8022
8023              mPendingInputEventCount -= 1;
8024              Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
8025                      mPendingInputEventCount);
8026
8027              long eventTime = q.mEvent.getEventTimeNano();
8028              long oldestEventTime = eventTime;
8029              if (q.mEvent instanceof MotionEvent) {8030                  MotionEvent me = (MotionEvent)q.mEvent;
8031                  if (me.getHistorySize() > 0) {8032                      oldestEventTime = me.getHistoricalEventTimeNano(0);
8033                  }
8034              }
8035              mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
8036              //分发事件
8037              deliverInputEvent(q);
8038          }
8039
8040          // We are done processing all input events that we can process right now
8041          // so we can clear the pending flag immediately.
8042          if (mProcessInputEventsScheduled) {8043              mProcessInputEventsScheduled = false;
8044              mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
8045          }
8046      }8048      private void deliverInputEvent(QueuedInputEvent q) {8049          Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
8050                  q.mEvent.getId());
8051              ...
8067
8068              InputStage stage;//根据不同的情况初始化不同的InputStage实例 可以看到总共有三种实例mSyntheticInputStage、mFirstPostImeInputStage、 mFirstInputStage
8069              if (q.shouldSendToSynthesizer()) {8070                  stage = mSyntheticInputStage;
8071              } else {8072                  stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
8073              }
8074
8075              if (q.mEvent instanceof KeyEvent) {8076                  Trace.traceBegin(Trace.TRACE_TAG_VIEW, "preDispatchToUnhandledKeyManager");
8077                  try {8078                      mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
8079                  } finally {8080                      Trace.traceEnd(Trace.TRACE_TAG_VIEW);
8081                  }
8082              }
8083
8084              if (stage != null) {8085                  handleWindowFocusChanged();//分发事件
8086                  stage.deliver(q);
8087              } else {//完成事件分发处理
8088                  finishInputEvent(q);
8089              }
8090          } finally {8091              Trace.traceEnd(Trace.TRACE_TAG_VIEW);
8092          }
8093      }

InputStage总共有七个子类初始化如下:

922      public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
923              int userId) {1147                  mSyntheticInputStage = new SyntheticInputStage();//将mSyntheticInputStage传入ViewPostImeInputStage的构造函数作为ViewPostImeInputStage的下一任处理
1148                  InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
1149                  InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
1150                          "aq:native-post-ime:" + counterSuffix);
1151                  InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
1152                  InputStage imeStage = new ImeInputStage(earlyPostImeStage,
1153                          "aq:ime:" + counterSuffix);
1154                  InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
1155                  InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
1156                          "aq:native-pre-ime:" + counterSuffix);
1157
1158                  mFirstInputStage = nativePreImeStage;
1159                  mFirstPostImeInputStage = earlyPostImeStage;}

他们的关系图如下:

子类的大致功能如下:

NativePreImeInputStage: 主要是为了将消息放到NativeActivity中去处理, NativeActivity和普通Acitivty的功能区别不大,只是很多代码都在native层去实现,这样执行效率更高,并且NativeActivity在游戏开发中很实用。

ViewPreImeInputStage: 从名字中就可得知,最后会调用Acitivity的所有view的onkeyPreIme方法,这样就给View在输入法处理key事件之前先得到消息并处理的机会。

ImeInputStage:ImeInputStage的onProcess方法会调用InputMethodManager的dispatchInputEvent方法处理消息。

EarlyPostImeInputStage:屏幕上有焦点的View会高亮显示,用来提示用户焦点所在。

NativePostImeInputStage:为了让IME处理完消息后能先于普通的Activity处理消息。

ViewPostImeInputStage: Acitivity和view处理各种消息。

SyntheticInputStage: 流水线的最后一级,经过层层过滤之后,到达这里的消息已经不多了,例如手机上的虚拟按键消息。

Activity和View的事件处理主要对应的是ViewPostImeInputStage

InputStage主要逻辑如下:

/frameworks/base/core/java/android/view/ViewRootImpl.java$InputStage
5287      abstract class InputStage {5288          private final InputStage mNext;
5289
5290          protected static final int FORWARD = 0;
5291          protected static final int FINISH_HANDLED = 1;
5292          protected static final int FINISH_NOT_HANDLED = 2;
5293
5294          private String mTracePrefix;
5295
5296          /**
5297           * Creates an input stage.
5298           * @param next The next stage to which events should be forwarded.
5299           */
5300          public InputStage(InputStage next) {5301              mNext = next;
5302          }
5303
5304          /**
5305           * Delivers an event to be processed.
5306           */
5307          public final void deliver(QueuedInputEvent q) {5308              if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {5309                  forward(q);
5310              } else if (shouldDropInputEvent(q)) {5311                  finish(q, false);
5312              } else {//当一个新的事件来临时会走到这里
5313                  traceEvent(q, Trace.TRACE_TAG_VIEW);
5314                  final int result;
5315                  try {//调用具体子类的onProcess
5316                      result = onProcess(q);
5317                  } finally {5318                      Trace.traceEnd(Trace.TRACE_TAG_VIEW);
5319                  }
5320                  apply(q, result);
5321              }
5322          }
5323
5324          /**
5325           * Marks the the input event as finished then forwards it to the next stage.
5326           */
5327          protected void finish(QueuedInputEvent q, boolean handled) {//当调用finish后后续的子类的OnProcess就不会再执行FLAG_FINISHED_HANDLED主要是返回给InputDispacther的
5328              q.mFlags |= QueuedInputEvent.FLAG_FINISHED;
5329              if (handled) {5330                  q.mFlags |= QueuedInputEvent.FLAG_FINISHED_HANDLED;
5331              }
5332              forward(q);
5333          }
5334
5335          /**
5336           * Forwards the event to the next stage.
5337           */
5338          protected void forward(QueuedInputEvent q) {5339              onDeliverToNext(q);
5340          }
5341
5342          /**
5343           * Applies a result code from {@link #onProcess} to the specified event.
5344           */
5345          protected void apply(QueuedInputEvent q, int result) {5346              if (result == FORWARD) {//事件在当前的子类无法处理,交给下一个子类
5347                  forward(q);
5348              } else if (result == FINISH_HANDLED) {//事件在当前的子类已经处理完毕
5349                  finish(q, true);
5350              } else if (result == FINISH_NOT_HANDLED) {//事件在当前子类没有处理但是不需要后续的处理
5351                  finish(q, false);
5352              } else {5353                  throw new IllegalArgumentException("Invalid result: " + result);
5354              }
5355          }
5356
5357          /**
5358           * Called when an event is ready to be processed.
5359           * @return A result code indicating how the event was handled.
5360           */
5361          protected int onProcess(QueuedInputEvent q) {5362              return FORWARD;
5363          }
5364
5365          /**
5366           * Called when an event is being delivered to the next stage.
5367           */
5368          protected void onDeliverToNext(QueuedInputEvent q) {5369              if (DEBUG_INPUT_STAGES) {5370                  Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);
5371              }
5372              if (mNext != null) {5373                  mNext.deliver(q);
5374              } else {5375                  finishInputEvent(q);
5376              }
5377          }
5378  ...
5390
5391          protected boolean shouldDropInputEvent(QueuedInputEvent q) {5392              if (mView == null || !mAdded) {5393                  Slog.w(mTag, "Dropping event due to root view being removed: " + q.mEvent);
5394                  return true;
5395              } else if ((!mAttachInfo.mHasWindowFocus
5396                      && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)
5397                      && !isAutofillUiShowing()) || mStopped
5398                      || (mIsAmbientMode && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_BUTTON))
5399                      || (mPausedForTransition && !isBack(q.mEvent))) {5400                  // This is a focus event and the window doesn't currently have input focus or
5401                  // has stopped. This could be an event that came back from the previous stage
5402                  // but the window has lost focus or stopped in the meantime.
5403                  if (isTerminalInputEvent(q.mEvent)) {5404                      // Don't drop terminal input events, however mark them as canceled.
5405                      q.mEvent.cancel();
5406                      Slog.w(mTag, "Cancelling event due to no window focus: " + q.mEvent);
5407                      return false;
5408                  }
5409
5410                  // Drop non-terminal input events.
5411                  Slog.w(mTag, "Dropping event due to no window focus: " + q.mEvent);
5412                  return true;
5413              }
5414              return false;
5415          }
5416  ...
5442      }

从代码中InpuStage的七个具体的子类的实现可了解到事件的分发主要在于子类的onProcess的实现,我们还是以Key事件看一下Activity和View的事件处理,具体是在ViewPostImeInputStage的onProcess的实现,在处理完事件后调用finishInputEvent将结果返回

6.activity和View的事件处理

上节说过Activity和View的事件处理是在ViewPostImeInputStage的onProcess中处理的:

/frameworks/base/core/java/android/view/ViewRootImpl.java$ViewPostImeInputStage
5818          @Override
5819          protected int onProcess(QueuedInputEvent q) {5820              if (q.mEvent instanceof KeyEvent) {5821                  return processKeyEvent(q); //按键事件处理
5822              } else {5823                  final int source = q.mEvent.getSource();
5824                  if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {5825                      return processPointerEvent(q);//触摸事件的处理
5826                  } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {5827                      return processTrackballEvent(q);//轨迹球事件的处理
5828                  } else {5829                      return processGenericMotionEvent(q); //手势事件的处理
5830                  }
5831              }
5832          }

这边可以看到根据不同的输入事件有不同的处理,这里我们触摸事件输入为例;

/frameworks/base/core/java/android/view/ViewRootImpl.java$ViewPostImeInputStage
6017          private int processPointerEvent(QueuedInputEvent q) {6018              final MotionEvent event = (MotionEvent)q.mEvent;
6019
6020              mAttachInfo.mUnbufferedDispatchRequested = false;
6021              mAttachInfo.mHandlingPointerEvent = true;//其中mView指的是DecorView,但是DecorView没有重写dispatchPointerEvent方法,所以调用了View的dispatchPointerEvent
6022              boolean handled = mView.dispatchPointerEvent(event);
6023              maybeUpdatePointerIcon(event);
6024              maybeUpdateTooltip(event);
6025              mAttachInfo.mHandlingPointerEvent = false;
6026              if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {6027                  mUnbufferedInputDispatch = true;
6028                  if (mConsumeBatchedInputScheduled) {6029                      scheduleConsumeBatchedInputImmediately();
6030                  }
6031              }
6032              return handled ? FINISH_HANDLED : FORWARD;
6033          }
/frameworks/base/core/java/android/view/View.java
14565      public final boolean dispatchPointerEvent(MotionEvent event) {14566          if (event.isTouchEvent()) {//DecorView重写了dispatchTouchEvent,所以会走到DecorView中
14567              return dispatchTouchEvent(event);
14568          } else {14569              return dispatchGenericMotionEvent(event);
14570          }
14571      }
/frameworks/base/core/java/com/android/internal/policy/DecorView.java
42      @Override
443      public boolean dispatchTouchEvent(MotionEvent ev) {444          final Window.Callback cb = mWindow.getCallback();//Window.Callback的实现有Activiy和Dialog,这里看Activity的至此开始View的事件分发流程
445          return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
446                  ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
447      }

事件的传递顺序 Activity —> DecorView(extends ViewGroup)—>ViewGruop----->…->View

具体View的事件分发流程参考 https://www.jianshu.com/p/238d1b753e64

7.finishInputEvent返回事件处理结果

/frameworks/base/core/java/android/view/ViewRootImpl.java$InputStage
8095      private void finishInputEvent(QueuedInputEvent q) {8096          Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
8097                  q.mEvent.getId());
8098
8099          if (q.mReceiver != null) {8100              boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
8101              boolean modified = (q.mFlags & QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY) != 0;
8102              if (modified) {8103                  Trace.traceBegin(Trace.TRACE_TAG_VIEW, "processInputEventBeforeFinish");
8104                  InputEvent processedEvent;
8105                  try {8106                      processedEvent =
8107                              mInputCompatProcessor.processInputEventBeforeFinish(q.mEvent);
8108                  } finally {8109                      Trace.traceEnd(Trace.TRACE_TAG_VIEW);
8110                  }
8111                  if (processedEvent != null) {8112                      q.mReceiver.finishInputEvent(processedEvent, handled);
8113                  }
8114              } else {//按键事件走这边
8115                  q.mReceiver.finishInputEvent(q.mEvent, handled);
8116              }
8117          } else {8118              q.mEvent.recycleIfNeededAfterDispatch();
8119          }
8120
8121          recycleQueuedInputEvent(q);
8122      }
/frameworks/base/core/java/android/view/InputEventReceiver.java
164      public final void finishInputEvent(InputEvent event, boolean handled) {165          if (event == null) {166              throw new IllegalArgumentException("event must not be null");
167          }
168          if (mReceiverPtr == 0) {169              Log.w(TAG, "Attempted to finish an input event but the input event "
170                      + "receiver has already been disposed.");
171          } else {172              int index = mSeqMap.indexOfKey(event.getSequenceNumber());
173              if (index < 0) {174                  Log.w(TAG, "Attempted to finish an input event that is not in progress.");
175              } else {176                  int seq = mSeqMap.valueAt(index);
177                  mSeqMap.removeAt(index);
178                  nativeFinishInputEvent(mReceiverPtr, seq, handled);
179              }
180          }
181          event.recycleIfNeededAfterDispatch();
182      }

可以看到处理结果通过JNI交给了Native层去发送:

/frameworks/base/core/jni/android_view_InputEventReceiver.cpp
3    static void nativeFinishInputEvent(JNIEnv* env, jclass clazz, jlong receiverPtr,
394          jint seq, jboolean handled) {
395      sp<NativeInputEventReceiver> receiver =
396              reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
397      status_t status = receiver->finishInputEvent(seq, handled);
398      if (status && status != DEAD_OBJECT) {
399          String8 message;
400          message.appendFormat("Failed to finish input event.  status=%d", status);
401          jniThrowRuntimeException(env, message.string());
402      }
403  }
124  status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) {
125      if (kDebugDispatchCycle) {
126          ALOGD("channel '%s' ~ Finished input event.", getInputChannelName().c_str());
127      }
128
129      status_t status = mInputConsumer.sendFinishedSignal(seq, handled);
130      if (status) {
131          if (status == WOULD_BLOCK) {
132            ...
147      }
148      return status;
149  }/frameworks/native/libs/input/InputTransport.cpp
1068  status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
1069      if (DEBUG_TRANSPORT_ACTIONS) {
1070          ALOGD("channel '%s' consumer ~ sendFinishedSignal: seq=%u, handled=%s",
1071                mChannel->getName().c_str(), seq, toString(handled));
1072      }
1073
1074      if (!seq) {
1075          ALOGE("Attempted to send a finished signal with sequence number 0.");
1076          return BAD_VALUE;
1077      }
1078
1079      // Send finished signals for the batch sequence chain first.
1080      size_t seqChainCount = mSeqChains.size();
1081      if (seqChainCount) {
1082          uint32_t currentSeq = seq;
1083          uint32_t chainSeqs[seqChainCount];
1084          size_t chainIndex = 0;
1085          for (size_t i = seqChainCount; i > 0; ) {
1086               i--;
1087               const SeqChain& seqChain = mSeqChains.itemAt(i);
1088               if (seqChain.seq == currentSeq) {
1089                   currentSeq = seqChain.chain;
1090                   chainSeqs[chainIndex++] = currentSeq;
1091                   mSeqChains.removeAt(i);
1092               }
1093          }
1094          status_t status = OK;
1095          while (!status && chainIndex > 0) {
1096              chainIndex--;//发送结果
1097              status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
1098          }
1099          if (status) {
1100              // An error occurred so at least one signal was not sent, reconstruct the chain.
1101              for (;;) {
1102                  SeqChain seqChain;
1103                  seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
1104                  seqChain.chain = chainSeqs[chainIndex];
1105                  mSeqChains.push(seqChain);
1106                  if (!chainIndex) break;
1107                  chainIndex--;
1108              }
1109              return status;
1110          }
1111      }
1112
1113      // Send finished signal for the last message in the batch.
1114      return sendUnchainedFinishedSignal(seq, handled);
1115  }
1117  status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
1118      InputMessage msg;
1119      msg.header.type = InputMessage::Type::FINISHED;
1120      msg.body.finished.seq = seq;
1121      msg.body.finished.handled = handled ? 1 : 0;//通过Socket发送给InputDispacther
1122      return mChannel->sendMessage(&msg);
1123  }

在4.2小节,我们知道创建InputManagerService和应用进程的Socket时将服务端给了InputManagerService,当有数据写入服务端时会调用 的handleReceiveCallback来处理输入结果

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
2727  int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
2728      InputDispatcher* d = static_cast<InputDispatcher*>(data);
2729
2730      {   ...
2740          bool notify;
2741          sp<Connection> connection = d->mConnectionsByFd[fd];
2742          if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
2743              if (!(events & ALOOPER_EVENT_INPUT)) {
2744                  ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
2745                        "events=0x%x",
2746                        connection->getInputChannelName().c_str(), events);
2747                  return 1;
2748              }
2749
2750              nsecs_t currentTime = now();
2751              bool gotOne = false;
2752              status_t status;
2753              for (;;) {
2754                  uint32_t seq;
2755                  bool handled;//从Socket获取应用进程返回的事件处理结果
2756                  status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
2757                  if (status) {
2758                      break;
2759                  }//构建doDispatchCycleFinishedLockedInterruptible的Command并加入到 mCommandQueue中并在//doDispatchCycleFinishedLockedInterruptible中取消ANR的计时和开启下一轮分发流程
2760                  d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
2761                  gotOne = true;
2762              }
2763              if (gotOne) {//执行mCommandQueue的command
2764                  d->runCommandsLockedInterruptible();
2765                  if (status == WOULD_BLOCK) {
2766                      return 1;
2767                  }
2768              }
2774
2775           ...
2794  }
}}4786  void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) {
4787      sp<Connection> connection = commandEntry->connection;
4788      const nsecs_t finishTime = commandEntry->eventTime;
4789      uint32_t seq = commandEntry->seq;
4790      const bool handled = commandEntry->handled;
4791      //通过seq找到放入WaitQueue中的dispatchEntry
4792      // Handle post-event policy actions.
4793      std::deque<DispatchEntry*>::iterator dispatchEntryIt = connection->findWaitQueueEntry(seq);
4794      if (dispatchEntryIt == connection->waitQueue.end()) {
4795          return;
4796      }
4797      DispatchEntry* dispatchEntry = *dispatchEntryIt;
4798      const nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
4799      if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
4800          ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(),
4801                ns2ms(eventDuration), dispatchEntry->eventEntry->getDescription().c_str());
4802      }
4803      reportDispatchStatistics(std::chrono::nanoseconds(eventDuration), *connection, handled);4818      // Dequeue the event and start the next cycle.
4819      // Because the lock might have been released, it is possible that the
4820      // contents of the wait queue to have been drained, so we need to double-check
4821      // a few things.
4822      dispatchEntryIt = connection->findWaitQueueEntry(seq);
4823      if (dispatchEntryIt != connection->waitQueue.end()) {
4824          dispatchEntry = *dispatchEntryIt;//将dispatchEntry从waitQueue和Anr监控中移除
4825          connection->waitQueue.erase(dispatchEntryIt);
4826          mAnrTracker.erase(dispatchEntry->timeoutTime,
4827                            connection->inputChannel->getConnectionToken());
4828          if (!connection->responsive) {
4829              connection->responsive = isConnectionResponsive(*connection);
4830          }
4831          traceWaitQueueLength(connection);
4832          if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
4833              connection->outboundQueue.push_front(dispatchEntry);
4834              traceOutboundQueueLength(connection);
4835          } else {
4836              releaseDispatchEntry(dispatchEntry);
4837          }
4838      }
4839       //为当前的Connection开始下一轮事件的分发
4840      // Start the next dispatch cycle for this connection.
4841      startDispatchCycleLocked(now(), connection);
4842  }

流程总结:

EventHub: 收集底层硬件设备tp报点。打开"/dev/input/"目录下的input设备,并将其注册到epoll的监控队列中。一旦对应设备上有可读的input事件,马上包装成event,上报给InputReader。

InputReader: 获取EventHub上报的input事件,通过deviceid,找到具体的InputDevice,然后匹配上对应的InputMapper来处理对应input事件。InputMapper最终会按对应的NotifyArgs数据结构对事件进行封装,并加入到ArgsQueue中。最终flush操作会将ArgsQueue中的每一个Arg取出来转成对应的Entry加入到InputDispatcher的mInboundQueue。

InputDispatcher:: InboundQueue队头取出事件,匹配焦点窗口,通过mConnectionsByFd 获取到对应的Connection,将eventEntry转化为DispatchEntry并加入到Connection的outboundQueue队列,同时通过Connection获取InputChannel将事件发送到客户端,再将DispatchEntry从outboundQueue移到waitQueue里,等待客户端完成处理反馈完成消息,而InputDispatcher收到消息后回调handleReceiveCallback,将DispatchEntry从waitQueue里移出。

ViewRootImpl: 调用NaitveInputEventReceiver的handleEvent()接收input事件,转成java层对应的事件,通过InputStage体系相关类按责任链的模式进行事件分发操作。事件分发处理完毕后会执行finishInputEvent,通过InputChannel 发送完成的message,给到服务端InputDispatcher回调InputDispatcher.handleReceiveCallback()。

AndroidInputSystem相关推荐

最新文章

  1. Java黑皮书课后题第10章:*10.19(Mersenne素数)
  2. 关于编译器的一个疑问
  3. Python之路,Day9 - 线程、进程、协程和IO多路复用
  4. C++目录遍历:使用第三方库boost.filesystem等
  5. UVA 11991——Easy Problem from Rujia Liu?
  6. python实例 75,76
  7. 算法中各种距离的介绍
  8. 电影AI修复,让重温经典有了新的可能
  9. 自己用过最好用的pdf转word软件
  10. 前端PDF文件转图片方法
  11. JavaScript笔记 Object对象
  12. 那些好玩的生成器网站(三)
  13. c语言基础知识怎么记,c语言基础学习-学C语言要熟记那些基本语句? 爱问知识人...
  14. composer 报错:composer [ReflectionException] Class Fxp\Composer\AssetPlugin\Repository\NpmRepository
  15. 在腾讯轻量云上搭建 CS:GO 服务器
  16. SCI和EI的索引号查询方法
  17. Python VUE3 + Django Ninja的后台管理系统
  18. Dremel的学习与理解
  19. 数学建模:预测性模型学习——灰色预测模型(GM(1,1)模型)
  20. EPROM工作原理2

热门文章

  1. Openstack-实践4.Manila 部署及功能验证
  2. VBUS引脚外围电路设计
  3. unity-摄像机跟随
  4. Java | Java 入门学习路线
  5. mysql存储过程中使用select count(*) into 变量名 from +表+ where条件的用法
  6. 新手福利:真机调试无需开发者证书
  7. 关于不能访问腾讯云服务器tomcat的问题解决
  8. 47、SimpleOrientationSensor
  9. 47件产品入选北极星建筑奖,包括北京朝阳站、望朝中心、前海腾讯数码大厦等地标亮点 | 美通社头条...
  10. 数据库MySQL备份命令,手动备份MySQL数据库