Understanding IPC in Android

Looking under the hood of Intents

Ayaan Javed
ProAndroidDev

--

In this article, we cover everything from what a process is in Android to how they communicate with each other. Along the way, we understand the sandboxing of a process and how Linux handles them.

Then we finally move on to binder, the actual heavy lifter for IPC.

Quick example

Say you send an Intent from your app with some location coordinates to Google map. If maps is installed, the system automagically opens it with the given coordinates.

This communication that took place between these two apps is Inter Process Communication.

Read on to find out more.

Before moving on to how processes communicate, lets take a step back and understand what exactly is a process (specially in the context of Android).

What is a process?

Here is a somewhat theoretical way of describing a process -

In computing, a process refers to an instance of a running program on a computer system. It is an independent entity that contains the program code and its current execution state, including the program counter (the address of the next instruction to be executed), processor registers, and the contents of memory associated with the program.

In simpler words, a process is your code in action.

In Android world, (almost) every app runs as an individual process. The operating system allocates a block of memory to every app when you run it along with a unique ID.

This concept is borrowed from the underlying Linux operating system. In fact, it is common to almost all operating systems. If you are reading this post on a computer, here is a way to check all the running processes on Windows or Linux.

Check running processes on your phone

To see the same on your phone, connect it to computer using adb. Then run this command —

adb shell ps
Output of the command with few highlighted processes. Find the full file here

The above screenshot shows the list of processes running on the device when it was in idle state. If you check out the entire file, there are around 800+ active processes.

We can safely assume that tons of processes/apps are always running at any given point of time.

Sandboxing of a process

Every process is provided with everything that it needs in its own little sandbox. Things like memory, registers, processing power as and when needed.

This wiki article talks more about it in detail.

After providing all of this to each app, the system enforces tight restrictions on the sandboxing ensuring security of the device overall. This makes sure that no app can meddle with anything outside its boundary. It also means that every app has its own memory space clearly defined.

Now that we have a fair idea of a process and its sandboxing, lets move on to their communication.

For our scenario let us take two apps, “Ayaan” and “Javed”.

“Ayaan” wants to send a hello message to “Javed”. But as we have seen, it seems impossible for an app to access the memory space of another app.

What we need is a mediator. The mediator needs to have access to the whole memory space, so it can take a message from one part of memory to another.

A bit about Linux processes

For this, we need to dive a bit into the underlying Linux OS.

The OS divides all the running software into two broad categories —

  • User space
  • Kernel space

Kernel space is like this closed knit group of trusted people who manage the core functionalities of the OS.

They have unrestricted access to the whole memory space. This group generally consists of kernel (of course) and many device drivers.

User space is the rest of the public which has tight restrictions upon it. Applications running in this space, like Android, cannot access the memory of others, including the kernel space software.

Since the requirement for method of IPC is that the mediator should have access to all memory space, the Android team added a driver to that close knit group.

This came to be known as the Binder driver.

Binder in Android

The Binder driver was given the sole responsibility of handling all IPC in Android.

Firing intent to start another activity? Binder will do that for you.

Sending a system wide broadcast? Binder’s your guy.

Interacting with any system service(like location manager)? Binder is there for you.

How does it do all of this?

Say phone app needs to send a message to maps. We know that both these processes are going to be in their sandbox.

Now with binder being in the kernel space, it has access to whole memory, including the memory stack of these apps. It takes the message from memory space of phone app and puts it in the memory of maps.

Binder is quite reliable to work with. But it gets a bit complex and cumbersome at times.

As in everything software, we have layers of abstraction over it making our life easier. Which layer you want to interact with depends on your use case. It also determines the amount of granularity(control) you get.

In the next few articles we’ll move from theory to actual code. First we’ll try and tackle the AIDL layer.

Until then, here are a few great posts if you want to know about binder -

--

--