AIDL language

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 {
        // Location defined elsewhere
        void teleport(Location baz, float speed);
        String getName();

        // ITeleportCallback defined elsewhere
        void methodWithCallback(ITeleportCallback callback);

        // ITeleportSession defined elsewhere
        ITeleportSession getASubInterface();
    }

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.

Binder allows many interfaces and binder objects to be shared through binder interfaces. AIDL interfaces frequently employ callbacks as part of method calls, such as with ITeleportCallback in the previous example. You can reuse callback objects between calls to the same method or calls to different methods. Another common use of interface types is for sub-interfaces or session objects to be returned from methods such as with ITeleportSession in the previous example. This nesting allows different APIs to be encapsulated at either the API or based on runtime state. For example, a session may represent ownership of a particular resource. When interfaces are passed around multiple times or returned to the client or server they came from, they always preserve pointer equality of the underlying binder object.

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 + - ! ~.