Android is a touchscreen-oriented Operating System. From the early days of its development, a major developers concern was providing acceptable touchscreen responsiveness. Many solutions appeared throughout the years, including custom CPU frequency scaling governors, custom touchscreen kernel drivers etc. All of these tweaks do their job right, however, there are corner cases where Android has some touchscreen lag.
Today, we are going to discuss a simple tweak, that might give a small performance boost for touchscreen operation, especially in high device load conditions. This tweak is targeting ARM devices, but it could also work on x86-based platforms. To understand how it works, we will need to introduce some computer science terms first. Just follow the instructions provided below to improve touchscreen responsiveness of your Android device with a simple tweak that requires root access.
In modern computing, a hardware device usually gathers the attention of the Operating System by sending a hardware interrupt to the CPU. When a CPU receives a hardware interrupt, it pauses anything it is doing right away and instead executes an instruction path that is predefined by the Operating System for the specific hardware interrupt (this is known in computer science as entering interrupt context).
To better understand how this works, consider the following example: On a desktop computer, the user moves the mouse. The mouse device then sends a hardware interrupt to the CPU. The CPU then executes some special code inside the Operating System that reads the current position of the mouse and then informs the program responsible for displaying the mouse pointer on the screen about this change in position. After completing this task, the CPU resumes its previous operation.
Each complete computing platform, whether it is a desktop PC or a mobile device, ships with a special hardware chip known as an interrupt controller. This chip is responsible for gathering interrupts from all the devices connected to the system and sending them to the CPU. By being placed between the source of the interrupt and the CPU, the interrupt controller can apply priorities to interrupts and send them to different CPUs on a multi-core device.
By default, the Linux kernel assigns all hardware interrupts to the first CPU core at boot. However, this approach introduces a rare but possible corner case: A single CPU core can process only one interrupt at a time. When there is a large amount of hardware interrupts arriving at the same time, some interrupts will be delayed. A simple solution to this issue is changing the CPUs allowed to service an interrupt (CPU affinity) depending on CPU load. This is known as Interrupt Balancing. In fact, desktop Linux distributions use such an Interrupt Balancing tool for a long time now. Recently, Qualcomm developers decided to enable an interrupt balancer on high-end devices with good results. However, most Android devices still do not feature an Interrupt Balancing tool.
Improve Touchscreen Responsiveness on Android with a Simple Tweak
So, how the touchscreen tweak works? The touchscreen tweak works by changing the affinity of the touchscreen interrupt. Since there is no automatic interrupt balancing on most Android devices, we change the CPU affinity manually. By assigning a CPU other than the first one to service the touchscreen interrupt, we make sure that when the interrupt is raised, the CPU will enter interrupt context as soon as possible, avoiding high interrupt load delays.
How to Enable the Touchscreen Tweak
- Identify the touchscreen interrupt
Linux holds a list of hardware interrupts under the /proc filesystem. You can see this list by executing the following command in a terminal app (as root):
In the command output, the first column lists the interrupt number, while the last two columns list the Interrupt Controller and the driver using the interrupt respectively. The touchscreen driver name varies between devices, but usually, it contains the word “touch” in it. Once you identify the touchscreen driver, take a look at the name of the interrupt controller that services it. If it is GIC (the main Interrupt Controller on ARM systems), then take a note of the interrupt number. If it is something else, then your touchscreen interrupt is passing through another controller before going to GIC. In that case, take a note of the interrupt number of that controller (msmgpio on our device, which has the number 240 assigned to it).
- Change the CPU affinity
You can easily change the CPU affinity of an interrupt on Linux through the /proc filesystem. CPU affinity configuration nodes are placed under /proc/irq/[IRQ_NO]/smp_affinity_list. To change the CPU affinity, we only need to echo the assigned CPUs to that node, for example:
echo 1 > /proc/irq/240/smp_affinity_list
Remember that on Linux the first CPU has the number 0. Normally, we could add more than one CPU cores to the smp_affinity_list node, and have more CPUs cover a single interrupt. However, the ARM GIC only supports one CPU core per interrupt. Also, we should mention that if the touchscreen interrupt passes through another Interrupt Controller before getting to GIC, then we actually change the CPU affinity of all the interrupts handled by that Interrupt Controller. Still, interrupt load on the newly assigned CPU core will be lower, giving some touchscreen performance benefit.
Lastly, please note that this tweak will not survive a device reboot. If you feel that this tweak improved your device performance, you can apply it at boot using an Init.d script.
Did this tweak improve your device responsiveness overall? Let us know in the comments section below.