Q1:android的输入事件从哪里来?
A1:从Input子系统中来,由EventHub来负责从Input系统中读取所有的事件
linux内核提供了一个Input子系统来实现的,Input子系统会在/dev/input/路径下创建我们硬件输入设备的节点
可以从/proc/bus/input/devices中读出eventXX相关的硬件设备
frameworks/native/services/inputflinger/
EventHub.cpp
1. 看构造方法:监听输入设备节点的删除和添加
static const char *DEVICE_PATH = "/dev/input"; EventHub::EventHub(void) { mEpollFd = epoll_create(EPOLL_SIZE_HINT); // 利用inotify机制监听/dev/input目录下的IN_DELETE和IN_CREATE事件:监听输入设备节点的删除和添加 mINotifyFd = inotify_init(); int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE); struct epoll_event eventItem; memset(&eventItem, 0, sizeof(eventItem)); eventItem.events = EPOLLIN; eventItem.data.u32 = EPOLL_ID_INOTIFY; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem); // 通过管道实现唤醒方法:参考EventHub::wake() int wakeFds[2]; result = pipe(wakeFds); mWakeReadPipeFd = wakeFds[0]; mWakeWritePipeFd = wakeFds[1]; eventItem.data.u32 = EPOLL_ID_WAKE; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem); }
2. 监听设备节点不是目的,获取这些设备的输入事件才是目的
当有EPOLL_ID_INOTIFY事件发生后,会触发EventHub::readNotifyLocked(),去call openDeviceLocked(devname)来添加设备
status_t EventHub::openDeviceLocked(const char *devicePath) { // 又会去监听这个设备的所有EPOLLIN事件:就能够读取这个设备(devicePath,可能是dev/input/event0)的输入事件啦 struct epoll_event eventItem; memset(&eventItem, 0, sizeof(eventItem)); eventItem.events = mUsingEpollWakeup ? EPOLLIN : EPOLLIN | EPOLLWAKEUP; eventItem.data.u32 = deviceId; epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem); addDeviceLocked(device); return 0; } // mDevices中保存里所有的输入设备 void EventHub::addDeviceLocked(Device* device) { mDevices.add(device->id, device); device->next = mOpeningDevices; mOpeningDevices = device; }
Q2:如果EventHub启动的不是足够早,会不会出现有些输入设备已经挂载好,因此不会通过inotify机制通知到EventHub
A2:可能,但是这种潜在的问题已被处理。
在构造方法中,mNeedToScanDevices(true),初始化为true
在第一次调用getEvents方法时,会走这条case,因此会主动去把当前所有已经挂载的输入设备都加载进来
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { if (mNeedToScanDevices) { mNeedToScanDevices = false; scanDevicesLocked(); mNeedToSendFinishedDeviceScan = true; } } void EventHub::scanDevicesLocked() { status_t res = scanDirLocked(DEVICE_PATH); }
Q3:哪一行代码是读入输入事件
A3:当然要找epoll_wait
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) { int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis); }
Q3:EventHub运行在哪个进程的哪个线程,何时启动
A3:system_server进程,InputReaderThread这个线程,system_server创建InputManagerService的实例并调用它的start()方法后它就开始运行啦
1. systemserver启动InputManagerService //创建InputManagerService的实例 inputManager = new InputManagerService(context); //创建WindowManagerService的实例,并直接把inputManager传递给WMS wm = WindowManagerService.main(context, inputManager, mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL, !mFirstBoot, mOnlyCore); //设置WMS的InputMonitor作为IMS的callback,这意味着IMS会把得到的输入事件交给WMS去处理 inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); //启动IMS inputManager.start(); 2. InputManagerService的创建和启动 //它需要创建一个HandlerThread去处理一些消息:比如 MSG_DELIVER_INPUT_DEVICES_CHANGED //它像个Java层的傀儡,实际工作都在native层实现,需要call nativeInit,在native创建一个实例,并保存到mPtr中 public InputManagerService(Context context) { this.mContext = context; this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); } //需要把HandlerThread中的Looper给到native,在native创建一个NativeInputManager,它才是核心,相当于native中的IMS com_android_server_input_InputManagerService.cpp static jlong nativeInit(JNIEnv* env, jclass clazz, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); return reinterpret_cast<jlong>(im); } //它需要一个context,因为在native需要通过call java的代码去获得些系统资源:PointerIcon //它需要IMS的实例,因为它需要回调 //它需要mLooper,不清楚怎么使用的? //最终要的是,它创建了EventHub的实例,它会去监听/dev/input目录下的IN_DELETE和IN_CREATE事件 //EventHub的getEvents是获取所有输入事件的唯一方法,注意,EventHub保存在InputManager中 //size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) : mLooper(looper), mInteractive(true) { JNIEnv* env = jniEnv(); mContextObj = env->NewGlobalRef(contextObj); mServiceObj = env->NewGlobalRef(serviceObj); sp<EventHub> eventHub = new EventHub(); mInputManager = new InputManager(eventHub, this, this); } //InputManager是个重要的类,但也非常简单,它组合了EventHub和NativeInputManager //且NativeInputManager有两重身份:ReaderPolicy+DispatcherPolicy //这里启动了两个线程:InputReaderThread+InputDispatcherThread nputManager::InputManager( const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) { mDispatcher = new InputDispatcher(dispatcherPolicy); mReader = new InputReader(eventHub, readerPolicy, mDispatcher); initialize(); } void InputManager::initialize() { mReaderThread = new InputReaderThread(mReader); mDispatcherThread = new InputDispatcherThread(mDispatcher); } //InputManagerService的启动其实也就是把这两个线程执行起来 status_t InputManager::start() { status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); return OK; } 3. InputReaderThread 作为一个Thread,run方法被call后,就会去执行它的threadLoop方法,它的mReader就是InputReader mReader = new InputReader(eventHub, readerPolicy, mDispatcher); void InputReader::loopOnce() { //读取一定数量的events,并交给相应的设备去处理 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); if (count) { processEventsLocked(mEventBuffer, count); } //processEventsForDeviceLocked(deviceId, rawEvent, batchSize); //InputDevice* device = mDevices.valueAt(deviceIndex); //device->process(rawEvents, count); //设备有变化时,要通知NativeInputManager if (inputDevicesChanged) { mPolicy->notifyInputDevicesChanged(inputDevices); } //交给mDispatcher处理 mQueuedListener->flush(); }