Android6.0 按键流程(一)读取设备事件
之前我们整理过一篇按键流程,但是不是太详细有的细节的地方有遗漏,今天在Android6.0上重新总结下,先从读取按键值作为第一篇。
一、初始化
InputManagerService在SystemServer中新建,然后调用了start函数,这里我们就不讲了,从InputManagerService的构造函数讲起。

- public InputManagerService(Context context) {
- this.mContext = context;
- this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
- mUseDevInputEventForAudioJack =
- context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
- Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
- + mUseDevInputEventForAudioJack);
- mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
- LocalServices.addService(InputManagerInternal.class, new LocalService());
- }
nativeInit在com_android_server_input_InputManagerService.cpp中,实现如下:
[java] view plain copy
- static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
- jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
- sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
- if (messageQueue == NULL) {
- jniThrowRuntimeException(env, "MessageQueue is not initialized.");
- return 0;
- }
- NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
- messageQueue->getLooper());
- im->incStrong(0);
- return reinterpret_cast<jlong>(im);
- }
新建了一个NativeInputManager对象,并且把这个对象返回了保存在了InputManagerService的mPtr对象中,这只是保存了c层对象的地址,所以只要使用long保存地址就行了。
下面我们看下其构造函数:
[java] view plain copy
- 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);
- {
- AutoMutex _l(mLock);
- mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
- mLocked.pointerSpeed = 0;
- mLocked.pointerGesturesEnabled = true;
- mLocked.showTouches = false;
- }
- mInteractive = true;
- sp<EventHub> eventHub = new EventHub();
- mInputManager = new InputManager(eventHub, this, this);
- }
新建了一个InputManager和EventHub。
InputManager对象是在InputManager.cpp文件中
[cpp] view plain copy
- InputManager::InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = new InputDispatcher(dispatcherPolicy);
- mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
- initialize();
- }
InputManager中新建了一个InputDispatcher和InputReader两个对象,然后调用了initialize函数:
[cpp] view plain copy
- void InputManager::initialize() {
- mReaderThread = new InputReaderThread(mReader);
- mDispatcherThread = new InputDispatcherThread(mDispatcher);
- }
这两个变量就是两个线程我们就不看其构造函数了。
接着在InputManagerService中又调了start函数:
[cpp] view plain copy
- public void start() {
- Slog.i(TAG, "Starting input manager");
- nativeStart(mPtr);
- // Add ourself to the Watchdog monitors.
- Watchdog.getInstance().addMonitor(this);
- registerPointerSpeedSettingObserver();
- registerShowTouchesSettingObserver();
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- updatePointerSpeedFromSettings();
- updateShowTouchesFromSettings();
- }
- }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
- updatePointerSpeedFromSettings();
- updateShowTouchesFromSettings();
- }
我们主要看下nativeStart函数:

- static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
- NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
- status_t result = im->getInputManager()->start();
- if (result) {
- jniThrowRuntimeException(env, "Input manager could not be started.");
- }
- }
我们先把InputManagerService保存的mPtr传下来的变量强制转成NativeInputManager,调用调用器getInputManager函数,也就是其InputManager的start函数

- status_t InputManager::start() {
- status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputDispatcher thread due to error %d.", result);
- return result;
- }
- result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputReader thread due to error %d.", result);
- mDispatcherThread->requestExit();
- return result;
- }
- return OK;
- }
二、EventHub
在上一节中,在NativeInputManager构造函数中,还新建了一个EventHub对象,下面我们就来介绍下:
我们先来分析下其构造函数:
[cpp] view plain copy
- EventHub::EventHub(void) :
- mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
- mOpeningDevices(0), mClosingDevices(0),
- mNeedToSendFinishedDeviceScan(false),
- mNeedToReopenDevices(false), mNeedToScanDevices(true),
- mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);
- LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
- mINotifyFd = inotify_init();//INotify机制
- int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);//监控dev/input目录
- LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d",
- DEVICE_PATH, errno);
- 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);//将这个iNotify的fd加入epoll
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
- int wakeFds[2];
- result = pipe(wakeFds);//创建了管道,用来唤醒epoll
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
- mWakeReadPipeFd = wakeFds[0];
- mWakeWritePipeFd = wakeFds[1];
- result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
- errno);
- result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
- errno);
- eventItem.data.u32 = EPOLL_ID_WAKE;
- result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
- errno);