Journey I- Handling Physical Inputs (From a Key Press to Event Handlers)

Nipun Arora
OS Journeys
Published in
4 min readAug 22, 2018

So here is a new series wherein we would go through various journeys of an operating system that is what all happens when we interact with an operating system.

To understand the basic concepts we will take examples of linux kernel, specifically the Android Operating System.

Some operating system concepts we would be going through in this journey are:

  • Interrupts and Interrupt Handling
  • Kernel Device Driver
  • Polling

The Journey begins with a tap on your mobile device’s touchscreen, which sends an electric hardware signal to your Android CPU, as a hardware interrupt.

These electrical signals are interrupts. The processor receives the interrupt and signals the operating system to enable the operating system to respond to the new data.Journey Block Diagram

An interrupt is just a signal to the processor, that the event requires special attention. An interrupt may be a hardware or a software interrupt. A software interrupt may be caused by execution of a predefined execution. A hardware interrupt, like in our case is caused by a key press or touch, or maybe a phone call. The processor receives the interrupt and signals the operating system to enable the operating system to respond to the new data.

Now, the next question which comes to our mind is how the operating system would know, how to react to a particular interrupt signal ?

Different devices are associated with different interrupts using a unique value associated with each interrupt. This enables the operating system to differentiate between interrupts and to know which hardware device caused which interrupt. In turn, the operating system can service each interrupt with its corresponding handler.

Now the next question which pops up is that where are these interrupt handlers found and in what form?

The interrupt handlers are actually the part of device drivers which are in turn part of the linux kernel, which you install anytime you connect a new device to your system. For your mobile phone, all the device drivers are pre-installed. Driver for a particular device contains the code to handle all the interrupts relating to that particular device. The code is usually written in C to make it faster.

Now, the interrupt handler performs the required functions. The interrupt handler runs a non-blocking code, i.e the code cannot be preempted by any other function requiring CPU. These functions run in a special context called interrupt context and cannot be switched.

Now the interrupt handler must satisfy these two requirements:

  1. The interrupt handler should execute its code as fast as possible and resume the execution of interrupted code.

2. The interrupt handler should execute completely all of the assigned work.

To combat these issues, the code is divided into 2 halves:

  1. The code which is executed quickly.(Top half)
  2. The code which is deferred for future execution.(Bottom half)

The complete cycle described above can be represented as :

Complete cycle describing what happens when an interrupt occurs.

Now, you must be thinking, there may be another interrupt, while an interrupt is executing, what would happen then ?

Normally all other interrupts are enabled, so other interrupts are serviced, but the current line is always disabled. Consequently, the same interrupt handler is never invoked concurrently to service a nested interrupt. This greatly simplifies writing your interrupt handler.

When the interrupt handler finishes its work, the interrupt line is freed.

On the other hand, Following series of events take place as android starts its GUI service(Window Manager Service).

  • The WindowManagerService class initialisation also initialises a message queue and starts a thread InputEventReader, A thread which is on constant lookout for input events.
  • The InputEventReader runs an infinite loop which busy waits on a JNI method readEvent().
  • The readEvent method further calls EventHub’s getEvent()(Responsible for converting raw linux event to android interface).
  • The getEvent function continuously polls certain file descriptors (/dev/input/***) for events.

Before moving ahead we will see what Polling is, Polling architecture is the exact opposite of interrupt driven that is in polling we keep waiting on a file descriptor until it is ready of IO.

Next, after we have an input event at /dev/input/eventXX registered by our device drivers, the poll functions returns with a POLLIN command indicating there is an event to be read, which is eventually read by the getEvent method and passed on to the GUI message queue.

We still miss a link, a link which connects the GUI message queue with client application, the WindowManagerService has another thread InputDispatcherThread which takes out events from the GUI message key and dispatches that to the message queue of the view in focus.

Next as the looper for that view runs it will pick up that event and run the logic written in its event handler and thus we arrive at our destination!

Thats it for this journey! We will be back with another one driving our way into the dynamics of an operating system. 😍

We are up for your queries and suggestions in the response section below. 😉

Co-Author: Sukhad Anand

--

--

Nipun Arora
OS Journeys

Android and Full Stack Backend Developer ,frolicking in the fascinating world of apps.