AndroidInputSystem
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主要做了以下三件事:
- 调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程,调用链:
- IMS.interceptKeyBeforeQueueing
- mWindowManagerCallbacks.interceptKeyBeforeQueueing
- mService.mPolicy.interceptKeyBeforeQueueing (mPolicy为WindowManagerPolicy)
- PhoneWindowManager.interceptKeyBeforeQueueing (实现WindowManagerPolicy的接口)
- 当mInputFilterEnabled=true(该值默认为false,可通过setInputFilterEnabled设置),则调用NativeInputManager.filterInputEvent过滤输入事件;
- 当返回值为false则过滤该事件,无机会交给InputDispatcher来分发
- 生成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分发事件的条件主要有以下三种:
- 执行enqueueInboundEventLocked方法前,mInboundQueue队列为空,执行完必然不再为空,则需要唤醒分发线程;
- 当事件类型为key事件,且发生一对按下和抬起操作,则需要唤醒;
- 当事件类型为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主要做了以下三件事:
调用dispatchOnceInnerLocked执行分发流程期间可能会加入需要执行的command
如果有command需要执行那么调用runCommandsLockedInterruptible来执行command
调用processAnrsLocked来检查是否发生ANR
线程执行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主要的工作:
- 根据mDispatchFrozen决定是否要冻结事件分发工作并不在分发事件
- 判断应用切换的事件是否超时
- mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量
- 根据事件的类型调用不同的分发函数,比如按键事件是dispatchKeyLocked
- 根据分发的返回值和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 }
在以下场景下,有可能无法分发事件:
- 当前时间小于唤醒时间(nextWakeupTime)的情况;
- policy需要提前拦截事件的情况;
- 需要drop事件的情况;
- 寻找聚焦窗口失败的情况
如果成功跳过以上所有情况,则会进入执行事件分发的过程。
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线程的主要工作如下:
- dispatchOnceInnerLocked(): 从InputDispatcher的
mInboundQueue
队列,取出事件EventEntry。另外该方法开始执行的时间点(currentTime)便是后续事件dispatchEntry的分发时间(deliveryTime) - dispatchKeyLocked():满足一定条件时会添加命令doInterceptKeyBeforeDispatchingLockedInterruptible;
- enqueueDispatchEntryLocked():生成事件DispatchEntry并加入connection的
outbound
队列 - startDispatchCycleLocked():从outboundQueue中取出事件DispatchEntry, 根据类型调用publishKeyEvent分发事件给focusWindow并将Event放入connection的
waitQueue
队列; - publishKeyEventz则调用InputChannel.sendMessage通过socket方式将消息发送给远程进程;
- 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相关推荐
最新文章
- Java黑皮书课后题第10章:*10.19(Mersenne素数)
- 关于编译器的一个疑问
- Python之路,Day9 - 线程、进程、协程和IO多路复用
- C++目录遍历:使用第三方库boost.filesystem等
- UVA 11991——Easy Problem from Rujia Liu?
- python实例 75,76
- 算法中各种距离的介绍
- 电影AI修复,让重温经典有了新的可能
- 自己用过最好用的pdf转word软件
- 前端PDF文件转图片方法
- JavaScript笔记 Object对象
- 那些好玩的生成器网站(三)
- c语言基础知识怎么记,c语言基础学习-学C语言要熟记那些基本语句? 爱问知识人...
- composer 报错:composer [ReflectionException] Class Fxp\Composer\AssetPlugin\Repository\NpmRepository
- 在腾讯轻量云上搭建 CS:GO 服务器
- SCI和EI的索引号查询方法
- Python VUE3 + Django Ninja的后台管理系统
- Dremel的学习与理解
- 数学建模:预测性模型学习——灰色预测模型(GM(1,1)模型)
- EPROM工作原理2
热门文章
- Openstack-实践4.Manila 部署及功能验证
- VBUS引脚外围电路设计
- unity-摄像机跟随
- Java | Java 入门学习路线
- mysql存储过程中使用select count(*) into 变量名 from +表+ where条件的用法
- 新手福利:真机调试无需开发者证书
- 关于不能访问腾讯云服务器tomcat的问题解决
- 47、SimpleOrientationSensor
- 47件产品入选北极星建筑奖,包括北京朝阳站、望朝中心、前海腾讯数码大厦等地标亮点 | 美通社头条...
- 数据库MySQL备份命令,手动备份MySQL数据库