The AIDL language is loosely based on the Java language. Files specify an interface contract and various data types and constants used in this contract.
Package
Every AIDL files starts with an optional package that corresponds to the package names in various backends. A package declaration looks like this:
package my.package;
Similar to Java, AIDL files must be in a folder structure matching their
package. Files with package my.package
must be in the folder my/package/
.
Types
In AIDL files, there are many places where types can be specified. For an exact list of types that are supported in the AIDL language, see AIDL backends types.
Annotations
Several parts of the AIDL language support annotations. For a list of annotations and where they can be applied, see AIDL annotations.
Imports
To use types defined in other interfaces, you must first add dependencies in the
build system. In cc_*
and java_*
Soong modules, where .aidl
files are used
directly under srcs
in Android platform builds, you can add directories
using the field aidl: { include_dirs: ... }
. For imports using
aidl_interface
, see
here.
An import looks like this:
import some.package.Foo; // explicit import
When importing a type in the same package, the package can be omitted. Though, omitting the package can lead to ambiguous import errors when types are specified without a package and put in the global namespace (generally all types should be namespaced):
import Foo; // same as my.package.Foo
Define types
AIDL files generally define types which are used as an interface.
Interfaces
Here is an example AIDL interface:
interface ITeleport {
void teleport(Location baz, float speed);
String getName();
}
An interface defines an object with a series of methods. Methods can either be
oneway
(oneway void doFoo()
) or synchronous. If an interface is defined as
oneway
(oneway interface ITeleport {...}
), then all methods in it are
implicitly oneway
. Oneway methods are dispatched asynchronously and cannot
return a result. One-way methods from the same thread to the same binder also
execute serially (though potentially on different threads). For a
discussion of how to setup threads, see AIDL backends thread
management.
Methods can have zero or more arguments. Arguments to methods can be
in
, out
, or inout
. For a discussion of how this affects arguments types,
see
AIDL backends directionality.
Parcelables
For a description of how to create backend-specific parcelables, AIDL backends custom parcelables.
Android 10 and higher support parcelable definitions directly in AIDL. This type of parcelable is called a structured parcelable. For further information on how structured and stable AIDL are related in the AIDL compiler and our build system, see Structured versus stable AIDL.
For example:
package my.package;
import my.package.Boo;
parcelable Baz {
@utf8InCpp String name = "baz";
Boo boo;
}
Unions
Android 12 and higher support union declarations. For example:
package my.package;
import my.package.FooSettings;
import my.package.BarSettings;
union Settings {
FooSettings fooSettings;
BarSettings barSettings;
@utf8InCpp String str;
int number;
}
Enums
Android 11 and higher support enum declarations. For example:
package my.package;
enum Boo {
A = 1 * 4,
B = 3,
}
Nested Type Declarations
Android 13 and higher support nested type declarations. For example:
package my.package;
import my.package.Baz;
interface IFoo {
void doFoo(Baz.Nested nested); // defined in my/package/Baz.aidl
void doBar(Bar bar); // defined below
parcelable Bar { ... } // nested type definition
}
Constants
Custom AIDL interfaces, parcelables, and unions can also contain integer and string constants, such as:
const @utf8InCpp String HAPPY = ":)";
const String SAD = ":(";
const byte BYTE_ME = 1;
const int ANSWER = 6 * 7;
Constant expressions
AIDL constants, array sizes, and enumerators can be specified using constant expressions. Expressions can use parentheses to nest operations. Constant expression values can be used with integral or float values.
true
and false
literals represent boolean values. Values with a .
but
without a suffix, such as 3.8
, are considered to be double values. Float
values have the f
suffix, such as 2.4f
. An integral value with the l
or
L
suffix indicates a 64-bit long value. Otherwise, integrals values get the
smallest value-preserving signed type between 8-bit (byte), 32-bit (int),
and 64-bit (long). So 256
is considered to be an int
, but 255 + 1
overflows to be the byte
0
. Hex values, such as 0x3
, are first interpreted
as the smallest value-preserving unsigned type between 32-bit and 64-bit
and then reinterpreted as unsigned values. So, 0xffffffff
has the int
value
-1
. Starting in Android 13, the suffix u8
can be
added to constants, such as 3u8
, to represent a byte
value. This suffix is
important so that a calculation, such as 0xffu8 * 3
, is interpreted as -3
with type byte
whereas 0xff * 3
is 765
with type int
.
Supported operators have C++ and Java semantics. In order from lowest to
highest precedence, binary operators are
|| && | ^ & == != < > <= >= << >> + - * / %
. Unary operators are + - ! ~
.