Inter Process Communication (IPC) using AIDL

Akshat Chaturvedi
Bobble Engineering
Published in
4 min readJul 29, 2024

AIDL stands for Android Interface Definition Language, is similar to any other IDLs (Interface Definition Language) precisely used for inter process communication in Android operating system.
First things first, a process in android is basically any application running on screen or in background on a device. so inter process communication basically termed for a phenomena of data getting shared between two application within the device. Android framework provides great utilities for the IPC namely messenger and AIDL. We’ll restrict our discussion to AIDL, and dig deep into it.

In android two processes cannot access each other’s memory, and at times it is required, and for the same, AIDL is used which defines a programming interface that is agreed by both server and client, here sever and client are referred as two processes, server is the one which is sending the data and client is the one which is receiving the data, this data is basically decomposed into marshalls which android os can understand. These marshalls are difficult to and very tedious to write, so android studio does this for automatically using AIDL.

A simple AIDL file looks like as shown…

/ IRemoteService.aidl
package com.example.android;

// Declare any non-default types here with import statements

/** Example service interface */
interface IRemoteService {
/** Request the process ID of this service, to do evil things with it. */
int getPid();

/** Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}

AIDL works on os level so things are less resource hungry and data sharing is faster.

Calling an AIDL to use it is really simple if you manage to connect to a service.

private val binder = object : IRemoteService.Stub() {

override fun getPid(): Int =
Process.myPid()

override fun basicTypes(
anInt: Int,
aLong: Long,
aBoolean: Boolean,
aFloat: Float,
aDouble: Double,
aString: String
) {
// Does nothing
}
}

An inter process communication using AIDL are direct function calls, and no assumptions are required about the thread on which these calls are made.

If the calls are made from the local process they are called on the same thread from which it’s called.

In case of the calls made from the remote process the calls are made from a thread pool, a platform that maintains inside your own process. Calls can be made from multiple unknown threads so the AIDL we implement should be completely thread safe.

By default, AIDL supports the following data types:

  • All primitive types (such as int, long, char, boolean, and so on)
  • Arrays of primitive types such as int[], String, CharSequence, List
  • All elements in the List must be one of the supported data types in this list or one of the other AIDL-generated interfaces or parcelables you've declared. A List may optionally be used as a parameterized type class (for example, List<String>). The actual concrete class that the other side receives is always an ArrayList, although the method is generated to use the List interface.
  • Map
  • All elements in the Map must be one of the supported data types in this list or one of the other AIDL-generated interfaces or parcelables you've declared. Parameterized type maps, (such as those of the form Map<String,Integer>) are not supported. The actual concrete class that the other side receives is always a HashMap, although the method is generated to use the Map interface. Consider using a Bundle as an alternative to Map.

To expose the interface to the clients we need to create a service in the server application which defines the functions declared in the AIDL interface.

class RemoteService : Service() {

override fun onCreate() {
super.onCreate()
}

override fun onBind(intent: Intent): IBinder {
// Return the interface
return binder
}


private val binder = object : IRemoteService.Stub() {
override fun getPid(): Int {
return Process.myPid()
}

override fun basicTypes(
anInt: Int,
aLong: Long,
aBoolean: Boolean,
aFloat: Float,
aDouble: Double,
aString: String
) {
// Does nothing
}
}
}

This bind service needs to be connected on the client end, and the implemented functions can be called, hence easily letting us create an inter process communication ability to our applications.

If we intend to use only one to one communication then Android provides a utility called messenger, but if multiple requests are required to be made by different applications then AIDL is the best get away.

Thanks for Reading : )

--

--