AOSP Framework & Internals
6 min read

Touch Driver

Learn how the Linux input subsystem converts physical screen taps into coordinates using I2C controllers and the evdev interface.

The Hardware Bridge

When a user taps a smartphone screen, they are simply changing the capacitance of a sheet of glass. The Android framework requires structured coordinate objects to draw UI elements, not analog voltage drops. Something must bridge this massive gap between raw electrical signals and structured software events. That bridge starts at the hardware level with a touch controller and a kernel touch driver.

A touch controller is a dedicated integrated circuit bonded directly to the display glass. It continuously scans the screen for electrical changes. When a touch is detected, the controller does not send coordinates immediately. Instead, it pulls a General Purpose Input/Output (GPIO) pin low to trigger a hardware interrupt on the main CPU. This interrupt wakes up the kernel touch driver. The driver then communicates with the controller over an I2C or SPI bus to read the actual touch data.

Without this interrupt mechanism, the CPU would waste precious battery life constantly polling the screen for touches. Visualizing this hardware-to-software translation path clarifies where the physical analog signal becomes digital data. The flowchart below maps out this exact flow. Look for how the hardware interrupt always precedes the actual data read.

This flow ensures battery efficiency while providing an instant response to physical contact. The hardware has successfully captured the raw data. But a raw I2C response is useless to the operating system until it is translated.

The Universal Language

If every touch display manufacturer invented a proprietary way to send coordinate data, Android would require thousands of custom drivers. The kernel needs a universal language for all input devices, regardless of who built the hardware. This requirement is fulfilled by the standard Linux Input Subsystem.

The input subsystem is an abstraction layer that handles everything from basic USB mice to complex multi-touch displays. Once the touch driver retrieves the raw coordinates via I2C, it must translate them into a format the input subsystem understands. The driver accomplishes this by calling standard kernel functions. One key function is input_report_abs(). This specific call tells the kernel the absolute X and Y positions of the touch event.

By adhering to this standard, the obscure hardware details of the touch controller are hidden. The rest of the operating system simply sees a standard input device. The kernel now knows exactly where the touch occurred. But Android itself runs entirely in user-space, which is isolated from kernel memory.

Crossing the Boundary

Android needs a standardized way to pass kernel-level input events up to user-space applications. The Linux Input Core solves this isolation problem by exposing the event device interface, commonly known as evdev.

Every input device registered with the kernel gets a character device file assigned to it. These files are typically located at /dev/input/eventX. Android user-space components can open these files and read a continuous stream of structured event data. You can watch this data stream directly from a shell using the getevent command. This tool lets you inspect the raw events as they leave the kernel.

adb shell getevent -l /dev/input/event1

Common Mistake: Forgetting the -l flag will output a massive stream of meaningless hexadecimal numbers instead of human-readable labels.

Running this command with the flag while dragging a finger across the screen will output a massive wall of text. Each line represents a distinct coordinate update or state change. The Android InputManagerService relies on a native component called the EventHub to read directly from these device nodes. The EventHub parses these raw Linux events so they can be converted into motion objects for applications. This works perfectly for a single finger. But what happens when you use two fingers at once?

Keeping Fingers Straight

Simple X and Y coordinates work fine for a single mouse cursor. But a modern smartphone screen must track ten independent fingers simultaneously. If two fingers move at once, the system needs a way to know which coordinate update belongs to which finger. The kernel solves this ambiguity using the Multi-Touch Protocol.

There are two versions of this protocol, but Android heavily relies on Protocol B. In Protocol B, the kernel explicitly tracks individual fingers using independent slots. When a finger touches the screen, the driver assigns it a unique slot ID. As that specific finger moves, the driver only reports the updated X and Y coordinates for that active slot. When the finger lifts off the glass, the driver reports a tracking ID of -1 to signal the touch has ended.

This sequence diagram illustrates the reporting flow between the driver and the input core. This visual clarifies how multiple fingers are tracked over time without confusing their coordinates. Look for how the synchronization call is used to group related events into a single frame.

That input_sync() call is crucial to the entire input pipeline. It acts as a commit message. It tells the input subsystem that the driver has finished reporting all coordinates for this specific moment in time. Without it, user-space would not know when a batch of simultaneous multi-touch changes was complete.

input_mt_slot(input_dev, finger_id);
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, true);
input_report_abs(input_dev, ABS_MT_POSITION_X, x_coordinate);
input_report_abs(input_dev, ABS_MT_POSITION_Y, y_coordinate);
input_sync(input_dev); 

The journey of a touch event starts as an analog electrical change on a glass panel. A hardware controller translates that change into an interrupt and readable data. The kernel driver maps this data into the Linux Input Subsystem, tracking multiple fingers using slots. Finally, the evdev interface exposes this structured stream of coordinates to user-space.

Now the kernel has successfully handed the data off to the device files. But simply writing to a file is not the same as moving a UI element on screen. Something inside Android must constantly watch these files, parse the raw Linux events, and route them to the correct application window.