https://gist.github.com/jieyu/4262418
https://gist.github.com/jieyu/4262418/raw/c1d0fc34eac41be55017ac6d8fc3b4b46cc7fe94/AndroidInputEventPropagation.md
# Android Input Event Propagation This document discusses how an input event from user (e.g. user key stroke) is propagated in Android framework, and how it is delivered to the corresponding event handler in the application. This document is based on the code of Android 4.1.1_r6.1 (Jelly Bean). For each application, a `ViewRootImpl` object is created to handle communications with the remote system `WindowManagerService` object. The communication is through a Linux pipe which is encapsulated in an `InputChannel` object (`mInputChannel` field in class `ViewRootImpl`). The `ViewRootImpl` object also registers an instance of `InputEventReceiver` when the first `View` object is registered with it. frameworks/base/core/java/android/view/ViewRootImpl.java +482 482 public void setView(View view, ...) { ... 626 mInputEventReceiver = new WindowInputEventReceiver(mInputChannel, Looper.myLooper()); ... 644 } The constructor of class `WindowInputEventReceiver` (class `WindowManagerService` extends from class `InputEventReceiver`) calls a native methond `nativeInit(...)`: frameworks/base/core/java/android/view/InputEventReceiver.java +58 58 public InputEventReceiver(InputChannel inputChannel, Looper looper) { ... 66 mInputChannel = inputChannel; 67 mMessageQueue = looper.getQueue(); 68 mReceiverPtr = nativeInit(this, inputChannel, mMessageQueue); ... 71 } Three parameters are passed to the native function `nativeInit`: 1) The receiver object itself; 2) The `InputChannel` object passed from the `ViewRootImpl` object. 3) The main message queue (an object of class `MessageQueue`) of the application. The native function `nativeInit` is shown as follows: frameworks/base/core/jni/android_view_InputEventReceiver.cpp +227 227 static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj, 228 jobject inputChannelObj, jobject messageQueueObj) { 229 sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env, 230 inputChannelObj); ... 236 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); ... 242 sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env, 243 receiverObj, inputChannel, messageQueue); 244 status_t status = receiver->initialize(); ... 254 } The function first gets a pointer to a `NativeInputChannel` object (line 229) and a pointer to a `NativeMessageQueue` object (line 236), then creates and initializes a `NativeInputEventReceiver` object (line 242-244) using these two pointers and the receiver object itself. In the `initialize()` function of class `NativeInputEventReceiver`, the file descriptor of the Linux pipe (which is passed from `ViewRootImpl` in the object of `InputChannel`) is sent to the looper for polling. When the file descriptor becomes readable which means the system `WindowManagerService` object has detected an input event from the kernel, a callback function will be invoked. frameworks/base/core/jni/android_view_InputEventReceiver.cpp +92 92 status_t NativeInputEventReceiver::initialize() { 93 int receiveFd = mInputConsumer.getChannel()->getFd(); 94 mMessageQueue->getLooper()->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, this, NULL); 95 return OK; 96 } The callback function is the `handleEvent(...)` function in the same class `NativeInputEventReceiver`: frameworks/base/core/jni/android_view_InputEventReceiver.cpp +119 119 int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) { ... 132 JNIEnv* env = AndroidRuntime::getJNIEnv(); 133 status_t status = consumeEvents(env, false /*consumeBatches*/, -1); 134 mMessageQueue->raiseAndClearException(env, "handleReceiveCallback"); 135 return status == OK || status == NO_MEMORY ? 1 : 0; 136 } 138 status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, 139 bool consumeBatches, nsecs_t frameTime) { ... 187 inputEventObj = android_view_KeyEvent_fromNative(env, 188 static_cast<KeyEvent*>(inputEvent)); ... 208 env->CallVoidMethod(mReceiverObjGlobal, 209 gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj); ... 224 } As shown above, function `handleEvent(...)` invokes a Java function `InputEventReceiver.dispatchInputEvent(...)` (line 208), which will eventually invoke `onInputEvent(...)` in class `WindowInputEventReceiver`: frameworks/base/core/java/android/view/ViewRootImpl.java +4223 4223 public void onInputEvent(InputEvent event) { 4224 enqueueInputEvent(event, this, 0, true); 4225 } This function will eventually call `doProcessInputEvents()` (line 4147) which will then call `deliverInputEvent(...)` (line 3109) which will then call `deliverKeyEvent(...)` (line 3495). Finally, the event will be dispatch to the `View` object by calling `mView.dispatchKeyEvent(event)` (line 3575). Now, the question is how the system `WindowManagerService` object detects events from the kernel? It is actually quite simple, it polls several device files (e.g. /dev/input/eventX) exposed by the kernel. For more details, refer to this [blog](http://cjix.info/blog/misc/internal-input-event-handling-in-the-linux-kernel-and-the-android-userspace/).